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

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,7 @@ 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`**
91
97
  - `socialProviders: undefined` uses built-in defaults (`google`, `x`)
92
98
  - `socialProviders: []` hides all social buttons
93
99
  - known social ids like `google` and `x` automatically reuse built-in icons unless you override `icon`
@@ -96,6 +102,8 @@ Rules:
96
102
  - known wallet ids automatically reuse built-in metadata like `installUrl` and detected `installed` state unless you override them
97
103
  - component props still override `initSDK({ signIn })` on a per-modal basis
98
104
 
105
+ The package still **exports** `signInWithGoogle` (Google Identity Services, optional FedCM) for **custom** integrations; the built-in **`SignInModal`** does **not** use it for Google.
106
+
99
107
  ## Address & balance
100
108
  ```tsx
101
109
  if (!account.isConnected) return <p>Please connect wallet</p>;
@@ -141,7 +149,7 @@ const quote = await withdraw.fetchQuote("USDT", "ETH", "200");
141
149
 
142
150
  ### Implementing a real `MarketDataProvider`
143
151
 
144
- Replace `createMockMarketDataProvider()` with your own implementation:
152
+ Replace `createMarketDataProvider()` with your own implementation:
145
153
 
146
154
  ```ts
147
155
  import type { MarketDataProvider } from "@ab-org/predicate-market-sdk";
@@ -243,4 +251,4 @@ These policies can be passed into your smart-wallet authorization flow so app ac
243
251
  >
244
252
  Withdraw
245
253
  </button>
246
- ```
254
+ ```
@@ -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,8 +1,8 @@
1
1
  import type { MarketDataProvider } from "../types.js";
2
2
  /**
3
- * Market data provider backed by merchant API.
4
- * - getSupportedTokens / getSupportedChains: from GET https://merchant.tomo.services/chains
5
- * - getQuote: mock (no quote API yet)
6
- * - getDepositAddress: from session (no deposit-address API in this service)
3
+ * Default `MarketDataProvider` backed by the merchant chains API.
4
+ * - getSupportedTokens / getSupportedChains: from GET `{merchantBase}/chains`
5
+ * - getQuote: local estimate until a dedicated quote API exists
6
+ * - getDepositAddress: session wallet address + fixed minimum (no deposit-address HTTP API here)
7
7
  */
8
- export declare function createMockMarketDataProvider(): MarketDataProvider;
8
+ export declare function createMarketDataProvider(): MarketDataProvider;
@@ -3,7 +3,7 @@ import { getEnv } from "../utils/env.js";
3
3
  const DEFAULT_MERCHANT_BASE_URL = "https://merchant.tomo.services";
4
4
  let cachedChains = null;
5
5
  /** Fallback when chains API fails (network error, 4xx/5xx, parse error, missing base URL). */
6
- const MOCK_CHAINS_FALLBACK = [
6
+ const DEFAULT_CHAINS_FALLBACK = [
7
7
  {
8
8
  chain_id: "56",
9
9
  network: "BSC",
@@ -36,10 +36,10 @@ async function fetchChainsFromApi() {
36
36
  cachedChains = chains;
37
37
  return chains;
38
38
  }
39
- return MOCK_CHAINS_FALLBACK;
39
+ return DEFAULT_CHAINS_FALLBACK;
40
40
  }
41
41
  catch {
42
- return MOCK_CHAINS_FALLBACK;
42
+ return DEFAULT_CHAINS_FALLBACK;
43
43
  }
44
44
  }
45
45
  function chainToChainInfo(chain) {
@@ -63,7 +63,7 @@ function deriveTokensFromChains(chains) {
63
63
  }
64
64
  return Array.from(bySymbol.values());
65
65
  }
66
- function computeMockQuote(request) {
66
+ function computeDefaultQuote(request) {
67
67
  const isStable = ["USDT", "USDC", "USD1"].includes(request.token);
68
68
  const slippage = isStable ? "0.3" : "1.0";
69
69
  const feeRate = request.direction === "withdraw" ? 0.001 : 0;
@@ -81,12 +81,12 @@ function computeMockQuote(request) {
81
81
  };
82
82
  }
83
83
  /**
84
- * Market data provider backed by merchant API.
85
- * - getSupportedTokens / getSupportedChains: from GET https://merchant.tomo.services/chains
86
- * - getQuote: mock (no quote API yet)
87
- * - getDepositAddress: from session (no deposit-address API in this service)
84
+ * Default `MarketDataProvider` backed by the merchant chains API.
85
+ * - getSupportedTokens / getSupportedChains: from GET `{merchantBase}/chains`
86
+ * - getQuote: local estimate until a dedicated quote API exists
87
+ * - getDepositAddress: session wallet address + fixed minimum (no deposit-address HTTP API here)
88
88
  */
89
- export function createMockMarketDataProvider() {
89
+ export function createMarketDataProvider() {
90
90
  return {
91
91
  async getSupportedTokens(_direction) {
92
92
  const chains = await fetchChainsFromApi();
@@ -100,7 +100,7 @@ export function createMockMarketDataProvider() {
100
100
  return list.map(chainToChainInfo);
101
101
  },
102
102
  async getQuote(request) {
103
- return computeMockQuote(request);
103
+ return computeDefaultQuote(request);
104
104
  },
105
105
  async getDepositAddress(_token, _chain) {
106
106
  const session = sessionStore.getState().session;
@@ -2,12 +2,14 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useState } from "react";
3
3
  import { sessionStore } from "@ab-org/sdk-core";
4
4
  import { getSDKConfig } from "../auth/config.js";
5
+ import { clearSocialAccountInstance as clearEmbeddedWalletAccount } from "../auth/walletAccount.js";
5
6
  import { resolveSocialProviders } from "./SignInModal.shared.js";
6
7
  import { SignInModalFooter, SignInModalFrame, SignInModalSocialSection, SignInModalWalletGrid, } from "./SignInModal.sections.js";
7
8
  import { useSignInModalController } from "./useSignInModalController.js";
8
9
  import { Toast } from "./components/Toast.js";
9
10
  export function clearSocialAccountInstance() {
10
11
  try {
12
+ clearEmbeddedWalletAccount();
11
13
  const storage = typeof localStorage !== "undefined" ? localStorage : null;
12
14
  const adapterId = storage?.getItem("ab:wallet:adapterId");
13
15
  const session = sessionStore.getState().session;
@@ -22,6 +24,7 @@ export function clearSocialAccountInstance() {
22
24
  storage?.removeItem("ab:wallet:adapterId");
23
25
  }
24
26
  catch {
27
+ clearEmbeddedWalletAccount();
25
28
  sessionStore.clearSession();
26
29
  }
27
30
  }
@@ -66,6 +66,20 @@ const IconFrame = ({ background, children, }) => (_jsx("div", { style: {
66
66
  justifyContent: "center",
67
67
  overflow: "hidden",
68
68
  }, children: children }));
69
+ const MetaMaskWalletIcon = () => (_jsx(IconFrame, { background: "#1A0F07", children: _jsxs("svg", { width: "32", height: "32", viewBox: "0 0 32 32", fill: "none", children: [_jsx("path", { d: "M8 6L15 11L12 14L8 6Z", fill: "#E17726" }), _jsx("path", { d: "M24 6L17 11L20 14L24 6Z", fill: "#E27625" }), _jsx("path", { d: "M11 19L15 22V17L11 19Z", fill: "#F6851B" }), _jsx("path", { d: "M21 19L17 22V17L21 19Z", fill: "#F6851B" }), _jsx("path", { d: "M12 14L15 11V17L11 19L12 14Z", fill: "#763D16" }), _jsx("path", { d: "M20 14L17 11V17L21 19L20 14Z", fill: "#763D16" })] }) }));
70
+ const OKXWalletIcon = () => (_jsx(IconFrame, { background: "#FFFFFF", children: _jsxs("svg", { width: "30", height: "30", viewBox: "0 0 30 30", fill: "none", children: [_jsx("rect", { x: "2", y: "2", width: "8", height: "8", rx: "2", fill: "#050608" }), _jsx("rect", { x: "11", y: "2", width: "8", height: "8", rx: "2", fill: "#050608" }), _jsx("rect", { x: "20", y: "2", width: "8", height: "8", rx: "2", fill: "#050608" }), _jsx("rect", { x: "2", y: "11", width: "8", height: "8", rx: "2", fill: "#050608" }), _jsx("rect", { x: "20", y: "11", width: "8", height: "8", rx: "2", fill: "#050608" }), _jsx("rect", { x: "2", y: "20", width: "8", height: "8", rx: "2", fill: "#050608" }), _jsx("rect", { x: "11", y: "20", width: "8", height: "8", rx: "2", fill: "#050608" }), _jsx("rect", { x: "20", y: "20", width: "8", height: "8", rx: "2", fill: "#050608" })] }) }));
71
+ const CoinbaseWalletIcon = () => (_jsx(IconFrame, { background: "#0052FF", children: _jsxs("svg", { width: "30", height: "30", viewBox: "0 0 30 30", fill: "none", children: [_jsx("circle", { cx: "15", cy: "15", r: "10", stroke: "white", strokeWidth: "4" }), _jsx("rect", { x: "9", y: "13", width: "12", height: "4", rx: "2", fill: "white" })] }) }));
72
+ const TrustWalletIcon = () => (_jsx(IconFrame, { background: "#3375FF", children: _jsxs("svg", { width: "28", height: "28", viewBox: "0 0 28 28", fill: "none", children: [_jsx("path", { d: "M14 4L21 6.6V12.8C21 17.1 18.1 20.9 14 22.4C9.9 20.9 7 17.1 7 12.8V6.6L14 4Z", fill: "white" }), _jsx("path", { d: "M14 8L17 9.1V12.3C17 14.7 15.7 16.8 14 17.6C12.3 16.8 11 14.7 11 12.3V9.1L14 8Z", fill: "#3375FF" })] }) }));
73
+ const PhantomWalletIcon = () => (_jsx(IconFrame, { background: "linear-gradient(135deg, #6C47FF 0%, #9B6BFF 100%)", children: _jsxs("svg", { width: "30", height: "30", viewBox: "0 0 30 30", fill: "none", children: [_jsx("path", { d: "M8 18.5C8 14.4 11.2 11 15.3 11H20.4C21.8 11 23 12.2 23 13.6C23 15 21.8 16.2 20.4 16.2H14.7", stroke: "white", strokeWidth: "3", strokeLinecap: "round" }), _jsx("path", { d: "M10.5 14H19.5", stroke: "white", strokeWidth: "3", strokeLinecap: "round" }), _jsx("circle", { cx: "12", cy: "20", r: "1.4", fill: "white" }), _jsx("circle", { cx: "18", cy: "20", r: "1.4", fill: "white" })] }) }));
74
+ const RabbyWalletIcon = () => (_jsx(IconFrame, { background: "#EBF2FF", children: _jsxs("svg", { width: "30", height: "30", viewBox: "0 0 30 30", fill: "none", children: [_jsx("path", { d: "M11 7L13.5 13", stroke: "#7084FF", strokeWidth: "3", strokeLinecap: "round" }), _jsx("path", { d: "M19 7L16.5 13", stroke: "#7084FF", strokeWidth: "3", strokeLinecap: "round" }), _jsx("rect", { x: "8", y: "12", width: "14", height: "11", rx: "6", fill: "#7084FF" }), _jsx("circle", { cx: "13", cy: "17", r: "1.4", fill: "white" }), _jsx("circle", { cx: "17", cy: "17", r: "1.4", fill: "white" }), _jsx("path", { d: "M13 20C13.6 20.4 14.3 20.6 15 20.6C15.7 20.6 16.4 20.4 17 20", stroke: "white", strokeWidth: "1.8", strokeLinecap: "round" })] }) }));
75
+ /** Rainbow icon from wallet-adaptor-base (rainbowWallet.svg) */
76
+ const RainbowWalletIcon = () => (_jsx(IconFrame, { background: "linear-gradient(180deg, #174299 0%, #001E59 100%)", children: _jsxs("svg", { width: "32", height: "32", viewBox: "0 0 120 120", fill: "none", style: { overflow: "hidden", borderRadius: 12 }, children: [_jsxs("defs", { children: [_jsxs("radialGradient", { id: "rainbow_r1", cx: "0", cy: "0", r: "1", gradientUnits: "userSpaceOnUse", gradientTransform: "translate(26 94) rotate(-90) scale(74)", children: [_jsx("stop", { offset: "0.770277", stopColor: "#FF4000" }), _jsx("stop", { offset: "1", stopColor: "#8754C9" })] }), _jsxs("linearGradient", { id: "rainbow_l2", x1: "83", y1: "97", x2: "100", y2: "97", gradientUnits: "userSpaceOnUse", children: [_jsx("stop", { stopColor: "#FF4000" }), _jsx("stop", { offset: "1", stopColor: "#8754C9" })] }), _jsxs("linearGradient", { id: "rainbow_l3", x1: "23", y1: "20", x2: "23", y2: "37", gradientUnits: "userSpaceOnUse", children: [_jsx("stop", { stopColor: "#8754C9" }), _jsx("stop", { offset: "1", stopColor: "#FF4000" })] }), _jsxs("radialGradient", { id: "rainbow_r4", cx: "0", cy: "0", r: "1", gradientUnits: "userSpaceOnUse", gradientTransform: "translate(26 94) rotate(-90) scale(58)", children: [_jsx("stop", { offset: "0.723929", stopColor: "#FFF700" }), _jsx("stop", { offset: "1", stopColor: "#FF9901" })] }), _jsxs("linearGradient", { id: "rainbow_l5", x1: "68", y1: "97", x2: "84", y2: "97", gradientUnits: "userSpaceOnUse", children: [_jsx("stop", { stopColor: "#FFF700" }), _jsx("stop", { offset: "1", stopColor: "#FF9901" })] }), _jsxs("linearGradient", { id: "rainbow_l6", x1: "23", y1: "52", x2: "23", y2: "36", gradientUnits: "userSpaceOnUse", children: [_jsx("stop", { stopColor: "#FFF700" }), _jsx("stop", { offset: "1", stopColor: "#FF9901" })] }), _jsxs("radialGradient", { id: "rainbow_r7", cx: "0", cy: "0", r: "1", gradientUnits: "userSpaceOnUse", gradientTransform: "translate(26 94) rotate(-90) scale(42)", children: [_jsx("stop", { offset: "0.59513", stopColor: "#00AAFF" }), _jsx("stop", { offset: "1", stopColor: "#01DA40" })] }), _jsxs("radialGradient", { id: "rainbow_r8", cx: "0", cy: "0", r: "1", gradientUnits: "userSpaceOnUse", gradientTransform: "translate(51 97) scale(17 45.3333)", children: [_jsx("stop", { stopColor: "#00AAFF" }), _jsx("stop", { offset: "1", stopColor: "#01DA40" })] }), _jsxs("radialGradient", { id: "rainbow_r9", cx: "0", cy: "0", r: "1", gradientUnits: "userSpaceOnUse", gradientTransform: "translate(23 69) rotate(-90) scale(17 322.37)", children: [_jsx("stop", { stopColor: "#00AAFF" }), _jsx("stop", { offset: "1", stopColor: "#01DA40" })] })] }), _jsx("path", { d: "M20 38H26C56.9279 38 82 63.0721 82 94V100H94C97.3137 100 100 97.3137 100 94C100 53.1309 66.8691 20 26 20C22.6863 20 20 22.6863 20 26V38Z", fill: "url(#rainbow_r1)" }), _jsx("path", { d: "M84 94H100C100 97.3137 97.3137 100 94 100H84V94Z", fill: "url(#rainbow_l2)" }), _jsx("path", { d: "M26 20L26 36H20L20 26C20 22.6863 22.6863 20 26 20Z", fill: "url(#rainbow_l3)" }), _jsx("path", { d: "M20 36H26C58.0325 36 84 61.9675 84 94V100H66V94C66 71.9086 48.0914 54 26 54H20V36Z", fill: "url(#rainbow_r4)" }), _jsx("path", { d: "M68 94H84V100H68V94Z", fill: "url(#rainbow_l5)" }), _jsx("path", { d: "M20 52L20 36L26 36L26 52H20Z", fill: "url(#rainbow_l6)" }), _jsx("path", { d: "M20 62C20 65.3137 22.6863 68 26 68C40.3594 68 52 79.6406 52 94C52 97.3137 54.6863 100 58 100H68V94C68 70.804 49.196 52 26 52H20V62Z", fill: "url(#rainbow_r7)" }), _jsx("path", { d: "M52 94H68V100H58C54.6863 100 52 97.3137 52 94Z", fill: "url(#rainbow_r8)" }), _jsx("path", { d: "M26 68C22.6863 68 20 65.3137 20 62L20 52L26 52L26 68Z", fill: "url(#rainbow_r9)" })] }) }));
77
+ /** Zerion icon from wallet-adaptor-base (zerionWallet.svg) */
78
+ const ZerionWalletIcon = () => (_jsx(IconFrame, { background: "#2962EF", children: _jsx("svg", { width: "28", height: "28", viewBox: "0 0 28 28", fill: "none", children: _jsx("path", { fill: "#fff", d: "M6.073 7c-.48 0-.665.593-.262.841l10.073 6.074a.577.577 0 0 0 .758-.139l4.43-5.814c.3-.404-.004-.962-.525-.962H6.073ZM21.904 21c.48 0 .67-.596.267-.844l-10.075-6.073a.569.569 0 0 0-.751.146l-4.437 5.813c-.301.404.012.958.534.958h14.462Z" }) }) }));
79
+ /** Brave Wallet icon from wallet-adaptor-base (braveWallet.svg), scaled */
80
+ const BraveWalletIcon = () => (_jsx(IconFrame, { background: "#FFF", children: _jsxs("svg", { width: "32", height: "32", viewBox: "-100 -100 2970 2970", fill: "none", style: { overflow: "hidden", borderRadius: 12 }, children: [_jsxs("defs", { children: [_jsxs("linearGradient", { id: "brave_a", y1: "51%", y2: "51%", children: [_jsx("stop", { offset: "0.4", stopColor: "#f50" }), _jsx("stop", { offset: "0.6", stopColor: "#ff2000" })] }), _jsxs("linearGradient", { id: "brave_b", x1: "2%", y1: "51%", x2: "51%", y2: "51%", children: [_jsx("stop", { offset: "0", stopColor: "#ff452a" }), _jsx("stop", { offset: "1", stopColor: "#ff2000" })] })] }), _jsx("path", { fill: "url(#brave_a)", d: "m2395 723 60-147-170-176c-92-92-288-38-288-38l-222-252H992L769 363s-196-53-288 37L311 575l60 147-75 218 250 953c52 204 87 283 234 387l457 310c44 27 98 74 147 74s103-47 147-74l457-310c147-104 182-183 234-387l250-953z" }), _jsx("path", { fill: "#fff", d: "M1935 524s287 347 287 420c0 75-36 94-72 133l-215 230c-20 20-63 54-38 113 25 60 60 134 20 210-40 77-110 128-155 120a820 820 0 0 1-190-90c-38-25-160-126-160-165s126-110 150-124c23-16 130-78 132-102s2-30-30-90-88-140-80-192c10-52 100-80 167-105l207-78c16-8 12-15-36-20-48-4-183-22-244-5s-163 43-173 57c-8 14-16 14-7 62l58 315c4 40 12 67-30 77-44 10-117 27-142 27s-99-17-142-27-35-37-30-77c4-40 48-268 57-315 10-48 1-48-7-62-10-14-113-40-174-57-60-17-196 1-244 6-48 4-52 10-36 20l207 77c66 25 158 53 167 105 10 53-47 132-80 192s-32 66-30 90 110 86 132 102c24 15 150 85 150 124s-119 140-159 165a820 820 0 0 1-190 90c-45 8-115-43-156-120-40-76-4-150 20-210 25-60-17-92-38-113l-215-230c-35-37-71-57-71-131s287-420 287-420l273 44c32 0 103-27 168-50 65-20 110-22 110-22s44 0 110 22 136 50 168 50c33 0 275-47 275-47zm-215 1328c18 10 7 32-10 44l-254 198c-20 20-52 50-73 50s-52-30-73-50a13200 13200 0 0 0-255-198c-16-12-27-33-10-44l150-80a870 870 0 0 1 188-73c15 0 110 34 187 73l150 80z" }), _jsx("path", { fill: "url(#brave_b)", d: "m1999 363-224-253H992L769 363s-196-53-288 37c0 0 260-23 350 123l276 47c32 0 103-27 168-50 65-20 110-22 110-22s44 0 110 22 136 50 168 50c33 0 275-47 275-47 90-146 350-123 350-123-92-92-288-38-288-38" })] }) }));
81
+ /** Bitget icon from wallet-adaptor-base (bitgetWallet.svg) */
82
+ const BitgetWalletIcon = () => (_jsx(IconFrame, { background: "#001F29", children: _jsx("svg", { width: "28", height: "28", viewBox: "0 0 512 512", fill: "none", children: _jsx("path", { d: "M219.948 95.7022C201.623 95.6929 183.33 95.6835 164.941 95.7116C153.822 95.7116 149.651 109.671 157.921 117.939L283.098 243.117C287.004 246.69 289.441 250.574 289.53 255.693C289.441 260.812 287.004 264.696 283.098 268.269L157.921 393.446C149.651 401.715 153.822 415.674 164.941 415.674C183.33 415.702 201.623 415.693 219.948 415.683C229.122 415.679 238.305 415.674 247.511 415.674C259.555 415.674 266.72 409.24 273.154 402.805L386.047 289.912C395.057 280.902 403.119 268.939 403.009 255.693C403.119 242.447 395.057 230.484 386.047 221.474L273.154 108.58C266.72 102.146 259.555 95.7116 247.511 95.7116C238.305 95.7116 229.122 95.7069 219.948 95.7022Z", fill: "#00F0FF" }) }) }));
69
83
  const walletIconTheme = {
70
84
  metamask: "#F6851B",
71
85
  okx: "#050608",
@@ -84,4 +98,29 @@ const WalletPlaceholder = ({ walletId, name }) => (_jsx(IconFrame, { background:
84
98
  color: walletIconTheme[walletId] ? "#FFFFFF" : colors.textSecondary,
85
99
  fontFamily: fonts.family,
86
100
  }, children: name.slice(0, 2).toUpperCase() }) }));
87
- export const DefaultWalletIcon = ({ walletId, name, }) => _jsx(WalletPlaceholder, { walletId: walletId, name: name });
101
+ export const DefaultWalletIcon = ({ walletId, name, }) => {
102
+ switch (walletId) {
103
+ case "metamask":
104
+ return _jsx(MetaMaskWalletIcon, {});
105
+ case "okx":
106
+ return _jsx(OKXWalletIcon, {});
107
+ case "coinbase":
108
+ return _jsx(CoinbaseWalletIcon, {});
109
+ case "trust":
110
+ return _jsx(TrustWalletIcon, {});
111
+ case "phantom":
112
+ return _jsx(PhantomWalletIcon, {});
113
+ case "rabby":
114
+ return _jsx(RabbyWalletIcon, {});
115
+ case "rainbow":
116
+ return _jsx(RainbowWalletIcon, {});
117
+ case "zerion":
118
+ return _jsx(ZerionWalletIcon, {});
119
+ case "brave":
120
+ return _jsx(BraveWalletIcon, {});
121
+ case "bitget":
122
+ return _jsx(BitgetWalletIcon, {});
123
+ default:
124
+ return _jsx(WalletPlaceholder, { walletId: walletId, name: name });
125
+ }
126
+ };
@@ -1,5 +1,5 @@
1
- import { type GoogleCredential } from "../auth/google.js";
2
- import { type TwitterAuthResult } from "../auth/twitter.js";
1
+ import type { GoogleCredential } from "../auth/google.js";
2
+ import type { TwitterAuthResult } from "../auth/twitter.js";
3
3
  import { type CubeSignerSession, type WalletSession } from "@ab-org/sdk-core";
4
4
  import type { WalletItem } from "./signInTypes.js";
5
5
  export interface SignInModalControllerOptions {
@@ -1,47 +1,41 @@
1
1
  import { useMemo, useState } from "react";
2
2
  import { getSDKConfig } from "../auth/config.js";
3
- import { signInWithGoogle } from "../auth/google.js";
4
- import { signInWithTwitter } from "../auth/twitter.js";
5
- import { CubistSocialProvider, describeSessionCapabilityPolicy, WalletConnector, createDefaultInjectedWalletRegistry, } from "@ab-org/sdk-core";
3
+ import { createOidcRelayAuth } from "../auth/oidcRelay.js";
4
+ import WalletAccount from "../auth/walletAccount.js";
5
+ import { getEnv } from "../utils/env.js";
6
+ import { describeSessionCapabilityPolicy, WalletConnector, createDefaultInjectedWalletRegistry, } from "@ab-org/sdk-core";
6
7
  import { resolveWalletItems } from "./SignInModal.shared.js";
8
+ function resolveOidcStage() {
9
+ return getEnv("STAGE").toLowerCase() === "prod" ? "prod" : "dev";
10
+ }
7
11
  export const useSignInModalController = ({ wallets, initialVisibleCount, onGoogleLogin, onTwitterLogin, onCubeSignerSession, onWalletConnected, onSocialLogin, onWalletSelect, }) => {
8
12
  const [expanded, setExpanded] = useState(false);
9
13
  const [loadingProvider, setLoadingProvider] = useState(null);
10
14
  const [loadingWalletId, setLoadingWalletId] = useState(null);
11
15
  const defaultWalletRegistry = useMemo(() => createDefaultInjectedWalletRegistry(), []);
12
16
  const sdkConfig = getSDKConfig();
13
- const cubistProvider = useMemo(() => {
14
- if (!sdkConfig.cubeSigner)
15
- return null;
16
- return new CubistSocialProvider({
17
- ...sdkConfig.cubeSigner,
18
- defaultSessionPolicy: sdkConfig.signIn?.sessionPolicy ?? sdkConfig.cubeSigner.defaultSessionPolicy,
19
- });
20
- }, [sdkConfig.cubeSigner, sdkConfig.signIn?.sessionPolicy]);
21
17
  const defaultWalletConnector = useMemo(() => new WalletConnector([
22
18
  ...defaultWalletRegistry.map((item) => item.provider),
23
- ...(cubistProvider ? [cubistProvider] : []),
24
- ]), [cubistProvider, defaultWalletRegistry]);
19
+ ]), [defaultWalletRegistry]);
25
20
  const resolvedWallets = useMemo(() => resolveWalletItems(wallets, defaultWalletRegistry), [defaultWalletRegistry, wallets]);
26
21
  const showExpandToggle = resolvedWallets.length > initialVisibleCount;
27
22
  const visibleWallets = expanded ? resolvedWallets : resolvedWallets.slice(0, initialVisibleCount);
28
23
  const isBusy = !!loadingProvider || !!loadingWalletId;
29
- const confirmCapabilitySession = async (providerId, cubistForPolicy) => {
30
- const cubist = cubistForPolicy ?? cubistProvider;
24
+ const confirmCapabilitySession = async (providerId, cubeSignerSession) => {
31
25
  const confirmation = sdkConfig.signIn?.sessionConfirmation;
32
- const policy = cubist?.cubeSignerAuth.defaultSessionPolicy;
26
+ const policy = cubeSignerSession && sdkConfig.cubeSigner
27
+ ? {
28
+ id: "preview",
29
+ ...(sdkConfig.signIn?.sessionPolicy ?? sdkConfig.cubeSigner.defaultSessionPolicy),
30
+ }
31
+ : undefined;
33
32
  if (confirmation?.enabled === false || !policy) {
34
33
  return true;
35
34
  }
36
35
  if (typeof window === "undefined" || typeof window.confirm !== "function") {
37
36
  return true;
38
37
  }
39
- const lines = describeSessionCapabilityPolicy(cubist?.cubeSignerAuth.defaultSessionPolicy
40
- ? {
41
- id: "preview",
42
- ...cubist.cubeSignerAuth.defaultSessionPolicy,
43
- }
44
- : undefined);
38
+ const lines = describeSessionCapabilityPolicy(policy);
45
39
  const message = [
46
40
  confirmation?.title ?? "Authorize smart-wallet session",
47
41
  confirmation?.message ?? `Continue with ${providerId} and create a capability session?`,
@@ -51,21 +45,6 @@ export const useSignInModalController = ({ wallets, initialVisibleCount, onGoogl
51
45
  .join("\n");
52
46
  return window.confirm(message);
53
47
  };
54
- const getCubistAndConnector = (config) => {
55
- if (!config.cubeSigner)
56
- return { cubist: null, connector: defaultWalletConnector };
57
- if (cubistProvider)
58
- return { cubist: cubistProvider, connector: defaultWalletConnector };
59
- const cubist = new CubistSocialProvider({
60
- ...config.cubeSigner,
61
- defaultSessionPolicy: config.signIn?.sessionPolicy ?? config.cubeSigner.defaultSessionPolicy,
62
- });
63
- const connector = new WalletConnector([
64
- ...defaultWalletRegistry.map((item) => item.provider),
65
- cubist,
66
- ]);
67
- return { cubist, connector };
68
- };
69
48
  const handleSocialClick = async (providerId) => {
70
49
  setLoadingProvider(providerId);
71
50
  try {
@@ -73,55 +52,57 @@ export const useSignInModalController = ({ wallets, initialVisibleCount, onGoogl
73
52
  if (!config.cubeSigner) {
74
53
  throw new Error("cubeSigner config is required for social login");
75
54
  }
76
- const { cubist, connector } = getCubistAndConnector(config);
77
- if (!cubist) {
78
- throw new Error("Cubist provider is unavailable");
79
- }
80
- const confirmed = await confirmCapabilitySession(providerId, cubist);
81
- if (!confirmed)
82
- return null;
55
+ const auth = createOidcRelayAuth({
56
+ stage: resolveOidcStage(),
57
+ googleClientId: config.googleClientId ?? "",
58
+ xClientId: config.twitterClientId ?? "",
59
+ });
83
60
  if (providerId === "google") {
84
61
  if (!config.googleClientId) {
85
62
  throw new Error("googleClientId is required for Google sign-in");
86
63
  }
87
- const credential = await signInWithGoogle(config.googleClientId);
88
- onGoogleLogin?.(credential);
89
- const session = await connector.connect(cubist.id, {
90
- payload: { type: "google", idToken: credential.idToken },
91
- });
92
- const cubeSignerSession = cubist.cubeSignerSession;
64
+ const oidcToken = await auth.loginByGoogle();
65
+ const authSource = "google";
66
+ WalletAccount.clearInstance();
67
+ await WalletAccount.getInstance(oidcToken, authSource, config.cubeSigner);
68
+ const session = WalletAccount.getWalletSession();
69
+ const cubeSignerSession = WalletAccount.getCubeSignerSession();
70
+ const confirmed = await confirmCapabilitySession(providerId, cubeSignerSession);
71
+ if (!confirmed) {
72
+ WalletAccount.clearInstance();
73
+ return null;
74
+ }
75
+ onGoogleLogin?.({ idToken: oidcToken });
93
76
  if (cubeSignerSession)
94
77
  onCubeSignerSession?.(cubeSignerSession);
95
78
  onSocialLogin?.(providerId);
79
+ if (!session) {
80
+ throw new Error("Failed to build wallet session from Google login");
81
+ }
96
82
  return session;
97
83
  }
98
84
  if (providerId === "x") {
99
85
  if (!config.twitterClientId) {
100
86
  throw new Error("twitterClientId is required for X sign-in");
101
87
  }
102
- const redirectUri = config.twitterRedirectUri ??
103
- (typeof window !== "undefined"
104
- ? `${window.location.origin}/auth/twitter-callback`
105
- : undefined);
106
- if (!redirectUri) {
107
- throw new Error("twitterRedirectUri is required for X sign-in");
88
+ const oidcToken = await auth.loginByX();
89
+ const authSource = "twitter";
90
+ WalletAccount.clearInstance();
91
+ await WalletAccount.getInstance(oidcToken, authSource, config.cubeSigner);
92
+ const session = WalletAccount.getWalletSession();
93
+ const cubeSignerSession = WalletAccount.getCubeSignerSession();
94
+ const confirmed = await confirmCapabilitySession(providerId, cubeSignerSession);
95
+ if (!confirmed) {
96
+ WalletAccount.clearInstance();
97
+ return null;
108
98
  }
109
- const result = await signInWithTwitter(config.twitterClientId, redirectUri);
110
- onTwitterLogin?.(result);
111
- const session = await connector.connect(cubist.id, {
112
- payload: {
113
- type: "twitter",
114
- params: {
115
- code: result.code,
116
- codeVerifier: result.codeVerifier,
117
- redirectUri,
118
- },
119
- },
120
- });
121
- const cubeSignerSession = cubist.cubeSignerSession;
99
+ onTwitterLogin?.({ code: "", codeVerifier: "", state: "" });
122
100
  if (cubeSignerSession)
123
101
  onCubeSignerSession?.(cubeSignerSession);
124
102
  onSocialLogin?.(providerId);
103
+ if (!session) {
104
+ throw new Error("Failed to build wallet session from X login");
105
+ }
125
106
  return session;
126
107
  }
127
108
  throw new Error(`Unsupported social provider: ${providerId}`);
@@ -152,7 +133,7 @@ export const useSignInModalController = ({ wallets, initialVisibleCount, onGoogl
152
133
  return session;
153
134
  }
154
135
  catch (error) {
155
- console.error(`[SDK] Wallet connect failed for ${walletId}:`, error);
136
+ console.error(`[predicate-market-sdk] Wallet connect failed for ${walletId}:`, error);
156
137
  throw error;
157
138
  }
158
139
  finally {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ab-org/predicate-market-sdk",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist/**/*",
@@ -20,6 +20,7 @@
20
20
  "registry": "https://registry.npmjs.org/"
21
21
  },
22
22
  "dependencies": {
23
+ "@cubist-labs/cubesigner-sdk": "^0.4.219",
23
24
  "axios": "^1.13.6",
24
25
  "qrcode-generator": "^2.0.4",
25
26
  "@ab-org/sdk-core": "0.0.1"