@ab-org/predicate-market-sdk 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  Prediction-market specific helpers built on top of `@ab-org/sdk-core`.
4
4
 
5
5
  ## Key features
6
- - Built-in wallet connection modal (social + plugin wallets)
6
+ - Built-in wallet connection modal (social via **OIDC relay** + `WalletAccount`, injected wallets via `WalletConnector` — **no FedCM** in `SignInModal` for Google/X)
7
7
  - Connection state via `createWalletConnectController()` and `createAccountController()` from `@ab-org/sdk-core`
8
8
  - Unified smart-wallet session metadata with capability policy support
9
9
  - High-level execution helpers via `createWalletExecutionController()`
@@ -29,10 +29,13 @@ import {
29
29
  import {
30
30
  createDepositController,
31
31
  createWithdrawController,
32
- createMockMarketDataProvider,
32
+ createMarketDataProvider,
33
33
  createPredicateMarketPolicyAdapter,
34
+ type CustodyAdapter,
34
35
  } from "@ab-org/predicate-market-sdk";
35
36
 
37
+ declare const custodyAdapter: CustodyAdapter;
38
+
36
39
  const connector = new WalletConnector([
37
40
  new MetaMaskProvider(),
38
41
  // new CubistSocialProvider(cubistClient)
@@ -43,7 +46,7 @@ const account = createAccountController();
43
46
  const execution = createWalletExecutionController();
44
47
 
45
48
  // Use the mock provider until real backend endpoints are ready
46
- const marketData = createMockMarketDataProvider();
49
+ const marketData = createMarketDataProvider();
47
50
 
48
51
  const deposit = createDepositController(custodyAdapter, marketData);
49
52
  const withdraw = createWithdrawController(custodyAdapter, marketData);
@@ -62,13 +65,15 @@ const policy = createPredicateMarketPolicyAdapter({
62
65
 
63
66
  ## Configure SignInModal
64
67
 
65
- The SDK ships with **bundled auth config** (Google client id, Twitter client id, CubeSigner env/org) so you can call `initSDK` with only `signIn` (and optionally `twitterRedirectUri` for your origin). Override via env (`NEXT_PUBLIC_*`) or by passing options to `initSDK`.
68
+ The SDK ships with **bundled auth config** (Google client id, Twitter client id, CubeSigner env/org) so you can call `initSDK` with only `signIn`. Override via env (`NEXT_PUBLIC_*`) or by passing options to `initSDK`.
69
+
70
+ **Google / X in `SignInModal`** use the SDK's **bundled OIDC relay auth**: a **popup** opens your **`NEXT_PUBLIC_RELAY_ORIGIN`** routes **`/relay/google`** and **`/relay/x`**, then the SDK's built-in **WalletAccount** bridge turns the returned OIDC token into the session provider.
66
71
 
67
72
  ```tsx
68
73
  import { initSDK, SignInModal } from "@ab-org/predicate-market-sdk";
69
74
 
70
75
  initSDK({
71
- // optional: override redirect for Twitter (origin-dependent)
76
+ // Optional: only used by other Twitter flows; SignInModal X login uses /relay/x on RELAY_ORIGIN
72
77
  twitterRedirectUri: typeof window !== "undefined" ? `${window.location.origin}/auth/twitter-callback` : undefined,
73
78
  signIn: {
74
79
  socialProviders: [
@@ -88,6 +93,17 @@ initSDK({
88
93
  ```
89
94
 
90
95
  Rules:
96
+ - **`NEXT_PUBLIC_RELAY_ORIGIN`** (or `RELAY_ORIGIN`) must match where you serve **`/relay/google`** and **`/relay/x`**
97
+
98
+ ### Funding chain & funding token (withdraw / balance)
99
+
100
+ - **`getChainInfo(chainId?)`** — resolves RPC, explorer metadata, native currency fields, and **`defaultFundingTokenAddress`** (per-chain default ERC-20 for the funding leg). If **`chainId`** is omitted or empty, defaults to **`3131`** (Tenderly BSC vnet). Built-in ids are **`3131`** and **`56`** (BSC mainnet); unknown ids throw.
101
+ - **`getFundingTokenAddress(chainId?)`** — same optional **`chainId`** as **`getChainInfo`**. If **`NEXT_PUBLIC_FUNDING_TOKEN_ADDRESS`** / **`FUNDING_TOKEN_ADDRESS`** or legacy **`NEXT_PUBLIC_BSC_USD1_ADDRESS`** / **`BSC_USD1_ADDRESS`** is set (checksummed `0x` + 40 hex), that value overrides defaults for **all** chains; otherwise returns **`getChainInfo(chainId).defaultFundingTokenAddress`**.
102
+ - **`DEFAULT_FUNDING_TOKEN_ADDRESS`** — shorthand for **`getChainInfo().defaultFundingTokenAddress`** (default funding chain **`3131`**).
103
+ - **`fetchFundingTokenBalance(address, { chainId, rpcUrl?, tokenAddress?, decimals?, displaySymbol? })`** — uses **`getChainInfo(chainId)`** for RPC when **`rpcUrl`** is omitted, **`getFundingTokenAddress(chainId)`** when **`tokenAddress`** is omitted, and **`decimals`** default **`chain.nativeCurrencyDecimals`** when omitted (override if your funding token uses different decimals).
104
+ - **`createFundingWithdrawExecutor({ chainId?, rpcUrl?, tokenAddress?, … })`** — uses the same **`chainId`** for **`getChainInfo`**, default token address (**`getFundingTokenAddress(chainId)`**), and order payload (default **`3131`** when **`chainId`** omitted).
105
+
106
+ **Type note:** **`EvmChainInfo`** includes **`defaultFundingTokenAddress`**. If you construct chain objects manually in TypeScript, add that field or use **`getChainInfo`** instead of literals.
91
107
  - `socialProviders: undefined` uses built-in defaults (`google`, `x`)
92
108
  - `socialProviders: []` hides all social buttons
93
109
  - known social ids like `google` and `x` automatically reuse built-in icons unless you override `icon`
@@ -96,6 +112,8 @@ Rules:
96
112
  - known wallet ids automatically reuse built-in metadata like `installUrl` and detected `installed` state unless you override them
97
113
  - component props still override `initSDK({ signIn })` on a per-modal basis
98
114
 
115
+ The package still **exports** `signInWithGoogle` (Google Identity Services, optional FedCM) for **custom** integrations; the built-in **`SignInModal`** does **not** use it for Google.
116
+
99
117
  ## Address & balance
100
118
  ```tsx
101
119
  if (!account.isConnected) return <p>Please connect wallet</p>;
@@ -141,7 +159,7 @@ const quote = await withdraw.fetchQuote("USDT", "ETH", "200");
141
159
 
142
160
  ### Implementing a real `MarketDataProvider`
143
161
 
144
- Replace `createMockMarketDataProvider()` with your own implementation:
162
+ Replace `createMarketDataProvider()` with your own implementation:
145
163
 
146
164
  ```ts
147
165
  import type { MarketDataProvider } from "@ab-org/predicate-market-sdk";
@@ -243,4 +261,4 @@ These policies can be passed into your smart-wallet authorization flow so app ac
243
261
  >
244
262
  Withdraw
245
263
  </button>
246
- ```
264
+ ```
@@ -0,0 +1,11 @@
1
+ export type OidcRelayStage = "dev" | "prod";
2
+ interface CreateOidcRelayAuthOptions {
3
+ stage: OidcRelayStage;
4
+ googleClientId: string;
5
+ xClientId: string;
6
+ }
7
+ export declare function createOidcRelayAuth({ stage, googleClientId, xClientId, }: CreateOidcRelayAuthOptions): {
8
+ loginByGoogle(): Promise<string>;
9
+ loginByX(): Promise<string>;
10
+ };
11
+ export {};
@@ -0,0 +1,107 @@
1
+ import { getEnv } from "../utils/env.js";
2
+ function getRelayOrigin() {
3
+ if (typeof window === "undefined") {
4
+ throw new Error("OIDC relay requires a browser environment");
5
+ }
6
+ if (window.location.hostname === "localhost") {
7
+ return window.location.origin;
8
+ }
9
+ const relayOrigin = getEnv("RELAY_ORIGIN");
10
+ if (!relayOrigin) {
11
+ throw new Error("RELAY_ORIGIN is not configured");
12
+ }
13
+ return relayOrigin;
14
+ }
15
+ function openRelayWindow(url, name) {
16
+ const width = 420;
17
+ const height = 640;
18
+ const top = (window.innerHeight - height) / 2 + window.screenY;
19
+ const left = (window.innerWidth - width) / 2 + window.screenX;
20
+ return window.open(url, name, `dialog=yes,top=${top}px,left=${left}px,width=${width}px,height=${height}px`);
21
+ }
22
+ function waitForOidcToken(popup, relayOrigin, timeoutMs = 120000) {
23
+ return new Promise((resolve, reject) => {
24
+ if (!popup) {
25
+ reject(new Error("Failed to open login popup"));
26
+ return;
27
+ }
28
+ let settled = false;
29
+ const cleanup = () => {
30
+ clearTimeout(timeout);
31
+ clearInterval(closedCheck);
32
+ window.removeEventListener("message", onMessage);
33
+ };
34
+ const finish = (fn) => {
35
+ if (settled)
36
+ return;
37
+ settled = true;
38
+ cleanup();
39
+ fn();
40
+ };
41
+ const timeout = window.setTimeout(() => {
42
+ try {
43
+ popup.close();
44
+ }
45
+ catch {
46
+ // Ignore popup close errors on timeout.
47
+ }
48
+ finish(() => reject(new Error("Login timeout")));
49
+ }, timeoutMs);
50
+ const onMessage = (event) => {
51
+ if (event.origin !== relayOrigin)
52
+ return;
53
+ if (event.data?.action !== "login")
54
+ return;
55
+ const payload = (event.data?.data ?? {});
56
+ if (payload.error) {
57
+ try {
58
+ popup.close();
59
+ }
60
+ catch {
61
+ // Ignore popup close errors after relay failure.
62
+ }
63
+ finish(() => reject(new Error(String(payload.error))));
64
+ return;
65
+ }
66
+ if (payload.oidcToken) {
67
+ try {
68
+ popup.close();
69
+ }
70
+ catch {
71
+ // Ignore popup close errors after success.
72
+ }
73
+ finish(() => resolve(payload.oidcToken));
74
+ }
75
+ };
76
+ const closedCheck = window.setInterval(() => {
77
+ if (popup.closed) {
78
+ finish(() => reject(new Error("Login cancelled by user")));
79
+ }
80
+ }, 400);
81
+ window.addEventListener("message", onMessage);
82
+ });
83
+ }
84
+ export function createOidcRelayAuth({ stage, googleClientId, xClientId, }) {
85
+ const relayOrigin = getRelayOrigin();
86
+ const buildUrl = (provider, clientId) => {
87
+ const target = window.location.origin;
88
+ const params = new URLSearchParams({
89
+ target,
90
+ stage,
91
+ eventId: Date.now().toString(),
92
+ action: "login",
93
+ clientId,
94
+ });
95
+ return `${relayOrigin}/relay/${provider}?${params.toString()}`;
96
+ };
97
+ return {
98
+ async loginByGoogle() {
99
+ const popup = openRelayWindow(buildUrl("google", googleClientId), "Google login");
100
+ return waitForOidcToken(popup, relayOrigin);
101
+ },
102
+ async loginByX() {
103
+ const popup = openRelayWindow(buildUrl("x", xClientId), "X login");
104
+ return waitForOidcToken(popup, relayOrigin);
105
+ },
106
+ };
107
+ }
@@ -0,0 +1,20 @@
1
+ import { type CubeSignerConfig, type CubeSignerSession, type WalletAuthSource, type WalletProvider, type WalletProviderRequest, type WalletSession } from "@ab-org/sdk-core";
2
+ export declare class EmbeddedWalletAccountProvider implements WalletProvider {
3
+ private readonly provider;
4
+ constructor(provider: WalletProvider);
5
+ request<T = unknown>(payload: WalletProviderRequest): Promise<T>;
6
+ disconnect(): Promise<void>;
7
+ eth_accounts(): Promise<string[]>;
8
+ eth_chainId(): Promise<string>;
9
+ }
10
+ export default class WalletAccount {
11
+ private static instance;
12
+ private static instanceToken;
13
+ private static walletSession;
14
+ private static cubeSignerSession;
15
+ static clearInstance(): void;
16
+ static getWalletSession(): WalletSession | null;
17
+ static getCubeSignerSession(): CubeSignerSession | null;
18
+ static getInstance(oidcToken: string, authSource: WalletAuthSource, cubeSignerConfig: CubeSignerConfig): Promise<EmbeddedWalletAccountProvider>;
19
+ }
20
+ export declare function clearSocialAccountInstance(): void;
@@ -0,0 +1,267 @@
1
+ import { EvmSigner } from "@cubist-labs/cubesigner-sdk";
2
+ import { CubeSignerAuth, createChainContext, createSessionCapabilityPolicy, } from "@ab-org/sdk-core";
3
+ const cubistCapabilities = [
4
+ "eth_accounts",
5
+ "eth_requestAccounts",
6
+ "eth_chainId",
7
+ "eth_signTransaction",
8
+ "personal_sign",
9
+ "eth_signTypedData_v4",
10
+ "wallet_disconnect",
11
+ ];
12
+ const evmChainIdMap = {
13
+ ETH: 1,
14
+ BSC: 56,
15
+ };
16
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
17
+ const toBigIntQuantity = (value) => {
18
+ if (typeof value === "bigint")
19
+ return value;
20
+ if (typeof value === "number") {
21
+ if (!Number.isInteger(value) || value < 0) {
22
+ throw new Error(`Invalid EVM quantity number: ${value}`);
23
+ }
24
+ return BigInt(value);
25
+ }
26
+ const trimmed = value.trim();
27
+ if (!trimmed) {
28
+ throw new Error("EVM quantity cannot be empty");
29
+ }
30
+ if (/^0x[0-9a-fA-F]+$/.test(trimmed) || /^\d+$/.test(trimmed)) {
31
+ return BigInt(trimmed);
32
+ }
33
+ throw new Error(`Invalid EVM quantity string: ${value}`);
34
+ };
35
+ const toHexQuantity = (value) => {
36
+ if (value === undefined)
37
+ return undefined;
38
+ return `0x${toBigIntQuantity(value).toString(16)}`;
39
+ };
40
+ const normalizeAccessList = (accessList) => {
41
+ if (!accessList)
42
+ return undefined;
43
+ return accessList.map((item) => ({
44
+ address: item.address,
45
+ storageKeys: item.storageKeys,
46
+ }));
47
+ };
48
+ const textEncoder = new TextEncoder();
49
+ const resolveTransactionType = (transaction) => {
50
+ if (transaction.type !== undefined) {
51
+ const normalized = toHexQuantity(transaction.type);
52
+ if (normalized === "0x0" || normalized === "0x1" || normalized === "0x2") {
53
+ return normalized;
54
+ }
55
+ throw new Error(`Unsupported EVM transaction type for Cubist: ${normalized}`);
56
+ }
57
+ if (transaction.maxFeePerGas !== undefined || transaction.maxPriorityFeePerGas !== undefined) {
58
+ return "0x2";
59
+ }
60
+ if (transaction.accessList?.length) {
61
+ return "0x1";
62
+ }
63
+ return "0x0";
64
+ };
65
+ const toCubistSignRequest = (address, chain, transaction) => {
66
+ const resolvedChainId = (transaction.chainId !== undefined ? Number(toBigIntQuantity(transaction.chainId)) : undefined) ??
67
+ evmChainIdMap[chain];
68
+ if (!resolvedChainId) {
69
+ throw new Error("Cubist signing requires an EVM chainId");
70
+ }
71
+ const type = resolveTransactionType(transaction);
72
+ const commonFields = {
73
+ from: transaction.from ?? address,
74
+ to: transaction.to,
75
+ data: transaction.data,
76
+ gas: toHexQuantity(transaction.gas),
77
+ nonce: toHexQuantity(transaction.nonce),
78
+ value: toHexQuantity(transaction.value),
79
+ };
80
+ const accessList = normalizeAccessList(transaction.accessList);
81
+ const tx = type === "0x2"
82
+ ? {
83
+ ...commonFields,
84
+ type,
85
+ ...(accessList ? { accessList } : {}),
86
+ maxFeePerGas: toHexQuantity(transaction.maxFeePerGas),
87
+ maxPriorityFeePerGas: toHexQuantity(transaction.maxPriorityFeePerGas),
88
+ }
89
+ : type === "0x1"
90
+ ? {
91
+ ...commonFields,
92
+ type,
93
+ ...(accessList ? { accessList } : {}),
94
+ gasPrice: toHexQuantity(transaction.gasPrice),
95
+ }
96
+ : {
97
+ ...commonFields,
98
+ type,
99
+ gasPrice: toHexQuantity(transaction.gasPrice),
100
+ };
101
+ return {
102
+ chain_id: resolvedChainId,
103
+ tx,
104
+ };
105
+ };
106
+ const getTransactionParam = (params) => {
107
+ const candidate = params?.[0];
108
+ if (!isRecord(candidate)) {
109
+ throw new Error("eth_signTransaction requires a transaction object");
110
+ }
111
+ return candidate;
112
+ };
113
+ const toHexBytes = (value) => {
114
+ if (/^0x[0-9a-fA-F]*$/.test(value))
115
+ return value;
116
+ return `0x${Array.from(textEncoder.encode(value))
117
+ .map((byte) => byte.toString(16).padStart(2, "0"))
118
+ .join("")}`;
119
+ };
120
+ const getMessageParam = (address, params) => {
121
+ const [first, second] = params ?? [];
122
+ if (typeof second === "string" && second.toLowerCase() === address.toLowerCase()) {
123
+ return String(first ?? "");
124
+ }
125
+ if (typeof first === "string" && first.toLowerCase() === address.toLowerCase()) {
126
+ return String(second ?? "");
127
+ }
128
+ return String(first ?? "");
129
+ };
130
+ const getTypedDataParam = (address, params) => {
131
+ const [first, second] = params ?? [];
132
+ if (typeof first === "string" && first.toLowerCase() === address.toLowerCase()) {
133
+ return typeof second === "string"
134
+ ? JSON.parse(second)
135
+ : (second ?? {});
136
+ }
137
+ return typeof second === "string"
138
+ ? JSON.parse(second)
139
+ : (second ?? first ?? {});
140
+ };
141
+ function createEmbeddedProvider({ session, address, chain, }) {
142
+ const signer = new EvmSigner(address, session.client);
143
+ return {
144
+ async request(payload) {
145
+ switch (payload.method) {
146
+ case "eth_accounts":
147
+ case "eth_requestAccounts":
148
+ return [address];
149
+ case "eth_chainId": {
150
+ const chainId = evmChainIdMap[chain];
151
+ if (!chainId) {
152
+ throw new Error(`CubistProvider: chain ${chain} does not expose an EVM chainId`);
153
+ }
154
+ return `0x${chainId.toString(16)}`;
155
+ }
156
+ case "eth_signTransaction": {
157
+ const transaction = getTransactionParam(payload.params);
158
+ const signRequest = toCubistSignRequest(address, chain, transaction);
159
+ return (await signer.signTransaction(signRequest));
160
+ }
161
+ case "personal_sign": {
162
+ const message = getMessageParam(address, payload.params);
163
+ return (await signer.signEip191({ data: toHexBytes(message) }));
164
+ }
165
+ case "eth_signTypedData_v4": {
166
+ const typedData = getTypedDataParam(address, payload.params);
167
+ const domain = typedData.domain;
168
+ const chainId = domain?.chainId !== undefined
169
+ ? Number(toBigIntQuantity(domain.chainId))
170
+ : evmChainIdMap[chain];
171
+ if (!chainId) {
172
+ throw new Error("CubistProvider: typed data signing requires an EVM chainId");
173
+ }
174
+ return (await signer.signEip712({
175
+ chain_id: chainId,
176
+ typed_data: typedData,
177
+ }));
178
+ }
179
+ default:
180
+ throw new Error(`CubistProvider: unsupported RPC method "${payload.method}"`);
181
+ }
182
+ },
183
+ async disconnect() {
184
+ await session.client.revokeSession();
185
+ },
186
+ };
187
+ }
188
+ export class EmbeddedWalletAccountProvider {
189
+ constructor(provider) {
190
+ this.provider = provider;
191
+ }
192
+ async request(payload) {
193
+ return this.provider.request(payload);
194
+ }
195
+ async disconnect() {
196
+ await this.provider.disconnect();
197
+ }
198
+ async eth_accounts() {
199
+ return this.request({ method: "eth_accounts" });
200
+ }
201
+ async eth_chainId() {
202
+ return this.request({ method: "eth_chainId" });
203
+ }
204
+ }
205
+ class WalletAccount {
206
+ static clearInstance() {
207
+ WalletAccount.instance = null;
208
+ WalletAccount.instanceToken = null;
209
+ WalletAccount.walletSession = null;
210
+ WalletAccount.cubeSignerSession = null;
211
+ }
212
+ static getWalletSession() {
213
+ return WalletAccount.walletSession;
214
+ }
215
+ static getCubeSignerSession() {
216
+ return WalletAccount.cubeSignerSession;
217
+ }
218
+ static async getInstance(oidcToken, authSource, cubeSignerConfig) {
219
+ if (WalletAccount.instance && WalletAccount.instanceToken === oidcToken) {
220
+ return WalletAccount.instance;
221
+ }
222
+ WalletAccount.clearInstance();
223
+ const auth = new CubeSignerAuth(cubeSignerConfig);
224
+ const cubeSignerSession = await auth.loginWithGoogle(oidcToken);
225
+ const keys = await cubeSignerSession.client.sessionKeys();
226
+ const evmKey = keys.find((key) => key.cached.key_type === "SecpEthAddr");
227
+ if (!evmKey) {
228
+ throw new Error("No EVM key found in CubeSigner session");
229
+ }
230
+ const address = evmKey.materialId;
231
+ const chain = "BSC";
232
+ const provider = createEmbeddedProvider({
233
+ session: cubeSignerSession,
234
+ address,
235
+ chain,
236
+ });
237
+ const wrappedProvider = new EmbeddedWalletAccountProvider(provider);
238
+ const capabilityPolicy = auth.defaultSessionPolicy
239
+ ? createSessionCapabilityPolicy(auth.defaultSessionPolicy)
240
+ : undefined;
241
+ WalletAccount.instance = wrappedProvider;
242
+ WalletAccount.instanceToken = oidcToken;
243
+ WalletAccount.cubeSignerSession = cubeSignerSession;
244
+ WalletAccount.walletSession = {
245
+ address,
246
+ chain,
247
+ provider: wrappedProvider,
248
+ walletType: "social",
249
+ authSource,
250
+ sessionId: `${authSource}:${address.toLowerCase()}`,
251
+ expiresAt: capabilityPolicy?.expiresAt,
252
+ capabilities: [...cubistCapabilities],
253
+ sessionData: cubeSignerSession.sessionData,
254
+ chainContext: createChainContext(chain),
255
+ capabilityPolicy,
256
+ };
257
+ return wrappedProvider;
258
+ }
259
+ }
260
+ WalletAccount.instance = null;
261
+ WalletAccount.instanceToken = null;
262
+ WalletAccount.walletSession = null;
263
+ WalletAccount.cubeSignerSession = null;
264
+ export default WalletAccount;
265
+ export function clearSocialAccountInstance() {
266
+ WalletAccount.clearInstance();
267
+ }
@@ -1,22 +1,2 @@
1
- export declare const testBsc: {
2
- readonly chainId: "3131";
3
- readonly name: "BSC_TENDERLY";
4
- readonly chainName: "BSC_TENDERLY";
5
- readonly nativeCurrencyName: "BSC";
6
- readonly nativeCurrencySymbol: "BSC";
7
- readonly nativeCurrencyDecimals: 18;
8
- readonly rpcUrls: readonly ["https://virtual.binance.eu.rpc.tenderly.co/e643ea28-32eb-4fb9-8116-90be24f7defa"];
9
- readonly blockExplorerUrl: "https://dashboard.tenderly.co/explorer/vnet/6593bc72-f548-497d-bff9-5be061436a48";
10
- readonly platformType: "EVM";
11
- readonly icon: "https://static.tomo.inc/token/bsc_new.svg";
12
- readonly supportSwap: true;
13
- readonly supportGift: true;
14
- readonly supportHistory: true;
15
- };
16
- export declare const clientIds: {
17
- readonly google: string;
18
- readonly x: string;
19
- readonly sdk: "MfLzAb2ItdDR3RZfE33ueqUhRf3mo1w0tBzLfExvLG72oUzvI6mgACtq19v6Vz7cmHVsfMBpbmr1fFU09sn30wbD";
20
- };
21
- export declare const BSC_USD1_ADDRESS = "0x8d0D000Ee44948FC98c9B98A4FA4921476f08B0d";
22
- export declare const BSC_USD1_PLATFORM_CONTRACT_ADDRESS = "0x1234567890123456789012345678901234567890";
1
+ export { ClientIds, DEFAULT_FUNDING_CHAIN_ID, DEFAULT_FUNDING_TOKEN_ADDRESS, getFundingTokenAddress, getChainInfo, type EvmChainInfo, } from "@ab-org/wallet-utils";
2
+ /** Demo / docs placeholder platform contract; replace in production. */
@@ -1,23 +1,3 @@
1
- import { getEnv } from "../utils/env.js";
2
- export const testBsc = {
3
- chainId: "3131",
4
- name: "BSC_TENDERLY",
5
- chainName: "BSC_TENDERLY",
6
- nativeCurrencyName: "BSC",
7
- nativeCurrencySymbol: "BSC",
8
- nativeCurrencyDecimals: 18,
9
- rpcUrls: ["https://virtual.binance.eu.rpc.tenderly.co/e643ea28-32eb-4fb9-8116-90be24f7defa"],
10
- blockExplorerUrl: "https://dashboard.tenderly.co/explorer/vnet/6593bc72-f548-497d-bff9-5be061436a48",
11
- platformType: "EVM",
12
- icon: "https://static.tomo.inc/token/bsc_new.svg",
13
- supportSwap: true,
14
- supportGift: true,
15
- supportHistory: true,
16
- };
17
- export const clientIds = {
18
- google: getEnv("GOOGLE_CLIENT_ID"),
19
- x: getEnv("X_CLIENT_ID"),
20
- sdk: "MfLzAb2ItdDR3RZfE33ueqUhRf3mo1w0tBzLfExvLG72oUzvI6mgACtq19v6Vz7cmHVsfMBpbmr1fFU09sn30wbD",
21
- };
22
- export const BSC_USD1_ADDRESS = "0x8d0D000Ee44948FC98c9B98A4FA4921476f08B0d";
23
- export const BSC_USD1_PLATFORM_CONTRACT_ADDRESS = "0x1234567890123456789012345678901234567890";
1
+ export { ClientIds, DEFAULT_FUNDING_CHAIN_ID, DEFAULT_FUNDING_TOKEN_ADDRESS, getFundingTokenAddress, getChainInfo, } from "@ab-org/wallet-utils";
2
+ /** Demo / docs placeholder platform contract; replace in production. */
3
+ // export const FUNDING_TOKEN_PLATFORM_CONTRACT_ADDRESS ="0x1234567890123456789012345678901234567890";
package/dist/index.d.ts CHANGED
@@ -8,6 +8,8 @@ export * from "./modules/withdraw.js";
8
8
  export * from "./modules/marketData.js";
9
9
  export * from "./modules/balanceQuery.js";
10
10
  export * from "./modules/withdrawExecutor.js";
11
+ export * from "./modules/api.js";
12
+ export * from "./modules/withdrawDirect.js";
11
13
  export * from "./policyAdapter.js";
12
14
  export * from "./ui/SignInModal.js";
13
15
  export * from "./ui/signInTypes.js";
@@ -17,3 +19,4 @@ export * from "./ui/WithdrawModal.js";
17
19
  export * from "./ui/components/DropdownField.js";
18
20
  export * from "./ui/components/DepositDetailsPanel.js";
19
21
  export * from "./walletUtils.js";
22
+ export * from "./constants/chains.js";
package/dist/index.js CHANGED
@@ -8,6 +8,8 @@ export * from "./modules/withdraw.js";
8
8
  export * from "./modules/marketData.js";
9
9
  export * from "./modules/balanceQuery.js";
10
10
  export * from "./modules/withdrawExecutor.js";
11
+ export * from "./modules/api.js";
12
+ export * from "./modules/withdrawDirect.js";
11
13
  export * from "./policyAdapter.js";
12
14
  export * from "./ui/SignInModal.js";
13
15
  export * from "./ui/signInTypes.js";
@@ -17,3 +19,5 @@ export * from "./ui/WithdrawModal.js";
17
19
  export * from "./ui/components/DropdownField.js";
18
20
  export * from "./ui/components/DepositDetailsPanel.js";
19
21
  export * from "./walletUtils.js";
22
+ // Re-export funding chain helpers so apps can import from package root
23
+ export * from "./constants/chains.js";
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Merchant API client (BaseUrl: https://merchant.tomo.services)
2
+ * Merchant API client
3
3
  * 基于 axios 封装,类型与文档一致。
4
4
  */
5
5
  import { type AxiosInstance } from "axios";
@@ -14,6 +14,10 @@ export interface TokenData {
14
14
  symbol: string;
15
15
  address: string;
16
16
  decimals: number;
17
+ /** 最小充值量(最小单位字符串,如 `"15000000"`) */
18
+ minimum_deposit?: string;
19
+ /** 是否为 USD 类稳定币 */
20
+ is_usd_stable?: boolean;
17
21
  }
18
22
  export interface ChainData {
19
23
  chain_id: string;
@@ -33,12 +37,12 @@ export interface PlatformRegisterResponseData {
33
37
  chain_id: string;
34
38
  }
35
39
  export type QuoteDirection = "deposit" | "withdraw";
36
- export interface QuoteRequest {
40
+ interface QuoteRequest {
37
41
  direction: QuoteDirection;
38
42
  chain_id: string;
39
43
  token_address: string;
40
44
  token_amount?: string;
41
- usd1_amount?: string;
45
+ dst_token_amount?: string;
42
46
  }
43
47
  export interface QuoteResponseData {
44
48
  token_address: string;
@@ -47,7 +51,7 @@ export interface QuoteResponseData {
47
51
  rate: string;
48
52
  chain_id: number;
49
53
  deposit_address?: string;
50
- usd1_amount?: string;
54
+ dst_token_amount?: string;
51
55
  token_amount?: string;
52
56
  expires_at?: string;
53
57
  }
@@ -58,7 +62,7 @@ export interface DepositOrderResponseData {
58
62
  source_chain_id: string;
59
63
  token_address: string;
60
64
  token_amount?: string;
61
- usd1_amount?: string;
65
+ dst_token_amount?: string;
62
66
  deposit_address?: string;
63
67
  source_tx_hash?: string;
64
68
  created_at?: string;
@@ -70,7 +74,7 @@ export interface WithdrawOrderResponseData {
70
74
  status: WithdrawOrderStatus;
71
75
  one_time_address?: string;
72
76
  chain_id: string;
73
- usd1_amount: string;
77
+ dst_token_amount: string;
74
78
  /** Fee (e.g. "0.01 USD1"); only present if backend includes it in GET /api/v1/orders/withdraw/:id. UI falls back to feeDisplay prop or "—". */
75
79
  fee?: string;
76
80
  target_chain_id: string;
@@ -123,7 +127,7 @@ export interface CreateOrderResponseData {
123
127
  payment_sessions: PaymentSessionResponseData[];
124
128
  }
125
129
  /**
126
- * 配置 Merchant API 的 baseURL(可选,默认 https://merchant.tomo.services)
130
+ * 配置 Merchant API 的 baseURL
127
131
  */
128
132
  export declare function configureMerchantApi(): void;
129
133
  /**
@@ -142,3 +146,4 @@ export declare function getDepositOrder(orderId: string): Promise<DepositOrderRe
142
146
  export declare function getWithdrawOrder(orderId: string): Promise<WithdrawOrderResponseData>;
143
147
  /** POST /order - 创建 NATIVE_SWAP 提现订单 */
144
148
  export declare function createOrder(body: CreateOrderRequest): Promise<CreateOrderResponseData>;
149
+ export {};