@swype-org/deposit 0.3.13 → 0.3.14
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/dist/{chunk-7Y4RWJI3.js → chunk-XYI3ZPQD.js} +421 -6
- package/dist/chunk-XYI3ZPQD.js.map +1 -0
- package/dist/index.cjs +423 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +159 -3
- package/dist/index.d.ts +159 -3
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +418 -3
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +2 -2
- package/dist/react.d.ts +2 -2
- package/dist/react.js +2 -2
- package/dist/{types-CCi4cpnQ.d.cts → types-DYsZwNXq.d.cts} +10 -3
- package/dist/{types-CCi4cpnQ.d.ts → types-DYsZwNXq.d.ts} +10 -3
- package/package.json +2 -2
- package/dist/chunk-7Y4RWJI3.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { D as DepositStatus, a as DepositResult, b as DepositError, c as DepositConfig, d as DepositRequest } from './types-
|
|
2
|
-
export { C as CheckoutConfig, e as CheckoutError, f as CheckoutErrorCode, g as CheckoutStatus, h as DepositErrorCode, S as SignerFunction, i as SignerRequest, j as SignerResponse, T as TransferSummary, k as getDisplayMessage } from './types-
|
|
1
|
+
import { D as DepositStatus, a as DepositResult, b as DepositError, c as DepositConfig, d as DepositRequest } from './types-DYsZwNXq.js';
|
|
2
|
+
export { C as CheckoutConfig, e as CheckoutError, f as CheckoutErrorCode, g as CheckoutStatus, h as DepositErrorCode, S as SignerFunction, i as SignerRequest, j as SignerResponse, T as TransferSummary, k as getDisplayMessage } from './types-DYsZwNXq.js';
|
|
3
3
|
|
|
4
4
|
declare const DEFAULT_WEBVIEW_BASE_URL = "https://pay.blink.cash";
|
|
5
5
|
type EventMap = {
|
|
@@ -73,6 +73,162 @@ declare class Deposit {
|
|
|
73
73
|
/** @deprecated Use {@link Deposit} instead. */
|
|
74
74
|
declare const Checkout: typeof Deposit;
|
|
75
75
|
|
|
76
|
+
/** Current wire-protocol version. Bump on breaking changes. */
|
|
77
|
+
declare const BRIDGE_PROTOCOL_VERSION = 1;
|
|
78
|
+
interface EIP6963ProviderInfo {
|
|
79
|
+
uuid: string;
|
|
80
|
+
name: string;
|
|
81
|
+
icon: string;
|
|
82
|
+
rdns: string;
|
|
83
|
+
}
|
|
84
|
+
interface EIP1193RequestArgs {
|
|
85
|
+
method: string;
|
|
86
|
+
params?: unknown[] | Record<string, unknown>;
|
|
87
|
+
}
|
|
88
|
+
interface EIP1193Provider {
|
|
89
|
+
request(args: EIP1193RequestArgs): Promise<unknown>;
|
|
90
|
+
on?: (event: string, listener: (...args: unknown[]) => void) => unknown;
|
|
91
|
+
removeListener?: (event: string, listener: (...args: unknown[]) => void) => unknown;
|
|
92
|
+
}
|
|
93
|
+
interface EIP6963ProviderDetail {
|
|
94
|
+
info: EIP6963ProviderInfo;
|
|
95
|
+
provider: EIP1193Provider;
|
|
96
|
+
}
|
|
97
|
+
/** Iframe → Parent: handshake, sent once on mount. */
|
|
98
|
+
interface BridgeHelloMessage {
|
|
99
|
+
type: 'blink:bridge-hello';
|
|
100
|
+
protocolVersion: number;
|
|
101
|
+
}
|
|
102
|
+
/** Parent → Iframe: list of installed wallets the iframe can borrow. */
|
|
103
|
+
interface WalletsAdvertisedMessage {
|
|
104
|
+
type: 'blink:wallets-advertised';
|
|
105
|
+
protocolVersion: number;
|
|
106
|
+
wallets: AdvertisedWallet[];
|
|
107
|
+
}
|
|
108
|
+
interface AdvertisedWallet {
|
|
109
|
+
uuid: string;
|
|
110
|
+
rdns: string;
|
|
111
|
+
name: string;
|
|
112
|
+
icon: string;
|
|
113
|
+
}
|
|
114
|
+
/** Iframe → Parent: invoke a JSON-RPC method on a top-frame wallet. */
|
|
115
|
+
interface RpcRequestMessage {
|
|
116
|
+
type: 'blink:rpc-request';
|
|
117
|
+
protocolVersion: number;
|
|
118
|
+
uuid: string;
|
|
119
|
+
id: string;
|
|
120
|
+
method: string;
|
|
121
|
+
params?: unknown[] | Record<string, unknown>;
|
|
122
|
+
}
|
|
123
|
+
/** Parent → Iframe: result of a previous `RpcRequestMessage`. */
|
|
124
|
+
interface RpcResponseMessage {
|
|
125
|
+
type: 'blink:rpc-response';
|
|
126
|
+
protocolVersion: number;
|
|
127
|
+
id: string;
|
|
128
|
+
result?: unknown;
|
|
129
|
+
error?: {
|
|
130
|
+
code: number;
|
|
131
|
+
message: string;
|
|
132
|
+
data?: unknown;
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
/** Parent → Iframe: forwarded EIP-1193 event from a top-frame wallet. */
|
|
136
|
+
interface RpcEventMessage {
|
|
137
|
+
type: 'blink:rpc-event';
|
|
138
|
+
protocolVersion: number;
|
|
139
|
+
uuid: string;
|
|
140
|
+
event: string;
|
|
141
|
+
args: unknown[];
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Iframe → Parent: ask "which advertised wallet has any of these flags
|
|
145
|
+
* (e.g. `isUniswapWallet`) set as a truthy property on its provider?".
|
|
146
|
+
* Used to disambiguate Reown registry entries that lack `rdns` (e.g.
|
|
147
|
+
* Uniswap, where Reown only ships `injected[].injectedId:
|
|
148
|
+
* 'isUniswapWallet'`). The parent reads `provider[flag]` defensively
|
|
149
|
+
* for each advertised provider and returns the first hit, or null.
|
|
150
|
+
*
|
|
151
|
+
* The parent answers each request once; the response is matched by
|
|
152
|
+
* `id`. Cost is local property reads on already-discovered providers —
|
|
153
|
+
* no network and no cross-frame I/O beyond the postMessage round-trip.
|
|
154
|
+
*/
|
|
155
|
+
interface ResolveByFlagRequestMessage {
|
|
156
|
+
type: 'blink:resolve-by-flag';
|
|
157
|
+
protocolVersion: number;
|
|
158
|
+
/** Request id, mirrored on the response so the iframe can route it. */
|
|
159
|
+
id: string;
|
|
160
|
+
/** Flag names to test in order; first truthy property wins. */
|
|
161
|
+
flags: string[];
|
|
162
|
+
}
|
|
163
|
+
/** Parent → Iframe: result of a previous `ResolveByFlagRequestMessage`. */
|
|
164
|
+
interface ResolveByFlagResponseMessage {
|
|
165
|
+
type: 'blink:resolve-by-flag-response';
|
|
166
|
+
protocolVersion: number;
|
|
167
|
+
id: string;
|
|
168
|
+
/** `null` when no advertised provider had any flag set. */
|
|
169
|
+
match: ResolveByFlagMatch | null;
|
|
170
|
+
}
|
|
171
|
+
interface ResolveByFlagMatch {
|
|
172
|
+
/** EIP-6963 `rdns` of the matched provider. */
|
|
173
|
+
rdns: string;
|
|
174
|
+
/** EIP-6963 `uuid` of the matched provider. */
|
|
175
|
+
uuid: string;
|
|
176
|
+
/** Which flag matched first (lets the caller log/telemeter). */
|
|
177
|
+
flag: string;
|
|
178
|
+
}
|
|
179
|
+
type BridgeMessage = BridgeHelloMessage | WalletsAdvertisedMessage | RpcRequestMessage | RpcResponseMessage | RpcEventMessage | ResolveByFlagRequestMessage | ResolveByFlagResponseMessage;
|
|
180
|
+
declare const ALLOWED_RPC_METHODS: Set<string>;
|
|
181
|
+
declare function parseBridgeMessage(data: unknown): BridgeMessage | null;
|
|
182
|
+
|
|
183
|
+
interface RegisteredProvider {
|
|
184
|
+
info: EIP6963ProviderInfo;
|
|
185
|
+
provider: EIP1193Provider;
|
|
186
|
+
}
|
|
187
|
+
interface WalletDiscovererHandle {
|
|
188
|
+
/** Snapshot of currently-registered providers. */
|
|
189
|
+
list(): RegisteredProvider[];
|
|
190
|
+
/** Look up a single provider by EIP-6963 uuid. */
|
|
191
|
+
get(uuid: string): EIP1193Provider | undefined;
|
|
192
|
+
/** Subscribe to registry changes. Returns an unsubscribe callback. */
|
|
193
|
+
subscribe(listener: (snapshot: RegisteredProvider[]) => void): () => void;
|
|
194
|
+
/**
|
|
195
|
+
* Re-dispatch `eip6963:requestProvider`. Wallets that wired up after
|
|
196
|
+
* page load (or after the initial sweep) will re-announce in response.
|
|
197
|
+
*/
|
|
198
|
+
requestProviders(): void;
|
|
199
|
+
/** Tear down listeners. After this, `list()` returns `[]`. */
|
|
200
|
+
destroy(): void;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Start discovering EIP-6963 providers in the current (top-level) frame.
|
|
204
|
+
*
|
|
205
|
+
* Safe to call multiple times — each handle owns its own listeners and
|
|
206
|
+
* registry; calling `destroy()` releases both. In practice, `createIframe`
|
|
207
|
+
* spins one handle per modal open.
|
|
208
|
+
*/
|
|
209
|
+
declare function createWalletDiscoverer(): WalletDiscovererHandle;
|
|
210
|
+
|
|
211
|
+
interface RpcHostHandle {
|
|
212
|
+
/** Tear down listeners and unsubscribe from all bridged providers. */
|
|
213
|
+
detach(): void;
|
|
214
|
+
}
|
|
215
|
+
interface RpcHostOptions {
|
|
216
|
+
/** Cross-origin iframe window we're talking to. */
|
|
217
|
+
iframeWindow: Window;
|
|
218
|
+
/** Origin of the iframe — origin-pin all postMessage send/receive. */
|
|
219
|
+
iframeOrigin: string;
|
|
220
|
+
/** Discoverer providing the EIP-6963 provider registry. */
|
|
221
|
+
discoverer: WalletDiscovererHandle;
|
|
222
|
+
/** Optional debug logger; defaults to a no-op. */
|
|
223
|
+
log?: (message: string, data?: Record<string, unknown>) => void;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Attach an RPC host to the given iframe. Listens on `window` for
|
|
227
|
+
* messages from the iframe and routes allowlisted JSON-RPC calls to the
|
|
228
|
+
* matching top-frame EIP-1193 provider.
|
|
229
|
+
*/
|
|
230
|
+
declare function attachRpcHost(options: RpcHostOptions): RpcHostHandle;
|
|
231
|
+
|
|
76
232
|
declare const VERSION = "0.3.0";
|
|
77
233
|
|
|
78
|
-
export { Checkout, DEFAULT_WEBVIEW_BASE_URL, Deposit, DepositConfig, DepositError, DepositRequest, DepositResult, DepositStatus, VERSION };
|
|
234
|
+
export { ALLOWED_RPC_METHODS, type AdvertisedWallet, BRIDGE_PROTOCOL_VERSION, type EIP1193Provider as BridgeEIP1193Provider, type BridgeHelloMessage, type BridgeMessage, Checkout, DEFAULT_WEBVIEW_BASE_URL, Deposit, DepositConfig, DepositError, DepositRequest, DepositResult, DepositStatus, type EIP6963ProviderDetail, type EIP6963ProviderInfo, type RegisteredProvider, type RpcEventMessage, type RpcHostHandle, type RpcHostOptions, type RpcRequestMessage, type RpcResponseMessage, VERSION, type WalletDiscovererHandle, type WalletsAdvertisedMessage, attachRpcHost, createWalletDiscoverer, parseBridgeMessage };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { Checkout, CheckoutError, DEFAULT_WEBVIEW_BASE_URL, Deposit, DepositError, getDisplayMessage } from './chunk-
|
|
1
|
+
export { ALLOWED_RPC_METHODS, BRIDGE_PROTOCOL_VERSION, Checkout, CheckoutError, DEFAULT_WEBVIEW_BASE_URL, Deposit, DepositError, attachRpcHost, createWalletDiscoverer, getDisplayMessage, parseBridgeMessage } from './chunk-XYI3ZPQD.js';
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
var VERSION = "0.3.0";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;AA2CO,IAAM,OAAA,GAAU","file":"index.js","sourcesContent":["export { Deposit, Checkout, DEFAULT_WEBVIEW_BASE_URL } from './checkout.ts';\nexport { DepositError, CheckoutError, getDisplayMessage } from './errors.ts';\nexport type { DepositErrorCode, CheckoutErrorCode } from './errors.ts';\nexport type {\n DepositConfig,\n CheckoutConfig,\n DepositStatus,\n CheckoutStatus,\n DepositRequest,\n DepositResult,\n SignerFunction,\n SignerRequest,\n SignerResponse,\n TransferSummary,\n} from './types.ts';\n\n// ── Wallet bridge (advanced) ──────────────────────────────────────────\n// Internal building blocks for the top-frame → iframe wallet bridge.\n// Default merchant integrations don't need these — `createIframe()` wires\n// them automatically. Re-exported so monorepo tests and any merchant\n// custom-iframe wrapper can poke at the protocol shapes.\nexport { createWalletDiscoverer } from './walletBridge/discover.ts';\nexport type { WalletDiscovererHandle, RegisteredProvider } from './walletBridge/discover.ts';\nexport { attachRpcHost } from './walletBridge/rpcHost.ts';\nexport type { RpcHostHandle, RpcHostOptions } from './walletBridge/rpcHost.ts';\nexport {\n ALLOWED_RPC_METHODS,\n BRIDGE_PROTOCOL_VERSION,\n parseBridgeMessage,\n} from './walletBridge/protocol.ts';\nexport type {\n AdvertisedWallet,\n BridgeMessage,\n BridgeHelloMessage,\n WalletsAdvertisedMessage,\n RpcRequestMessage,\n RpcResponseMessage,\n RpcEventMessage,\n EIP1193Provider as BridgeEIP1193Provider,\n EIP6963ProviderInfo,\n EIP6963ProviderDetail,\n} from './walletBridge/protocol.ts';\n\nexport const VERSION = '0.3.0';\n"]}
|
package/dist/react.cjs
CHANGED
|
@@ -94,6 +94,396 @@ function parseCloseRequest(data) {
|
|
|
94
94
|
return { type: "blink:close-request" };
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
+
// src/walletBridge/discover.ts
|
|
98
|
+
function createWalletDiscoverer() {
|
|
99
|
+
if (typeof window === "undefined") {
|
|
100
|
+
return makeNoopHandle();
|
|
101
|
+
}
|
|
102
|
+
const registry = /* @__PURE__ */ new Map();
|
|
103
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
104
|
+
let destroyed = false;
|
|
105
|
+
const onAnnounce = (event) => {
|
|
106
|
+
if (destroyed) return;
|
|
107
|
+
const detail = event.detail;
|
|
108
|
+
if (!isValidProviderDetail(detail)) {
|
|
109
|
+
console.info("[blink-bridge:parent] dropping malformed EIP-6963 announcement", {
|
|
110
|
+
rawInfo: event.detail && event.detail.info
|
|
111
|
+
});
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
const existing = registry.get(detail.info.uuid);
|
|
115
|
+
if (existing && existing.provider === detail.provider) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
console.info("[blink-bridge:parent] EIP-6963 announceProvider", {
|
|
119
|
+
rdns: detail.info.rdns,
|
|
120
|
+
name: detail.info.name,
|
|
121
|
+
uuid: detail.info.uuid
|
|
122
|
+
});
|
|
123
|
+
registry.set(detail.info.uuid, {
|
|
124
|
+
info: { ...detail.info },
|
|
125
|
+
provider: detail.provider
|
|
126
|
+
});
|
|
127
|
+
notify();
|
|
128
|
+
};
|
|
129
|
+
window.addEventListener("eip6963:announceProvider", onAnnounce);
|
|
130
|
+
requestProviders();
|
|
131
|
+
const RESWEEP_INTERVALS_MS = [500, 1500, 3e3, 6e3];
|
|
132
|
+
const reSweepTimers = [];
|
|
133
|
+
for (const ms of RESWEEP_INTERVALS_MS) {
|
|
134
|
+
reSweepTimers.push(
|
|
135
|
+
setTimeout(() => {
|
|
136
|
+
if (!destroyed) requestProviders();
|
|
137
|
+
}, ms)
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
function requestProviders() {
|
|
141
|
+
try {
|
|
142
|
+
window.dispatchEvent(new Event("eip6963:requestProvider"));
|
|
143
|
+
} catch {
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function notify() {
|
|
147
|
+
const snapshot = list();
|
|
148
|
+
for (const listener of listeners) {
|
|
149
|
+
try {
|
|
150
|
+
listener(snapshot);
|
|
151
|
+
} catch {
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
function list() {
|
|
156
|
+
return [...registry.values()];
|
|
157
|
+
}
|
|
158
|
+
return {
|
|
159
|
+
list,
|
|
160
|
+
get(uuid) {
|
|
161
|
+
return registry.get(uuid)?.provider;
|
|
162
|
+
},
|
|
163
|
+
subscribe(listener) {
|
|
164
|
+
listeners.add(listener);
|
|
165
|
+
return () => {
|
|
166
|
+
listeners.delete(listener);
|
|
167
|
+
};
|
|
168
|
+
},
|
|
169
|
+
requestProviders,
|
|
170
|
+
destroy() {
|
|
171
|
+
if (destroyed) return;
|
|
172
|
+
destroyed = true;
|
|
173
|
+
window.removeEventListener("eip6963:announceProvider", onAnnounce);
|
|
174
|
+
for (const t of reSweepTimers) clearTimeout(t);
|
|
175
|
+
registry.clear();
|
|
176
|
+
listeners.clear();
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
function makeNoopHandle() {
|
|
181
|
+
return {
|
|
182
|
+
list: () => [],
|
|
183
|
+
get: () => void 0,
|
|
184
|
+
subscribe: () => () => {
|
|
185
|
+
},
|
|
186
|
+
requestProviders: () => {
|
|
187
|
+
},
|
|
188
|
+
destroy: () => {
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
function isValidProviderDetail(value) {
|
|
193
|
+
if (!value || typeof value !== "object") return false;
|
|
194
|
+
const detail = value;
|
|
195
|
+
const info = detail.info;
|
|
196
|
+
const provider = detail.provider;
|
|
197
|
+
if (!info || !provider) return false;
|
|
198
|
+
if (typeof info.uuid !== "string" || info.uuid.length === 0) return false;
|
|
199
|
+
if (typeof info.name !== "string") return false;
|
|
200
|
+
if (typeof info.rdns !== "string") return false;
|
|
201
|
+
if (typeof provider.request !== "function") return false;
|
|
202
|
+
return true;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// src/walletBridge/protocol.ts
|
|
206
|
+
var BRIDGE_PROTOCOL_VERSION = 1;
|
|
207
|
+
var ALLOWED_RPC_METHODS = /* @__PURE__ */ new Set([
|
|
208
|
+
// Read
|
|
209
|
+
"eth_accounts",
|
|
210
|
+
"eth_blockNumber",
|
|
211
|
+
"eth_call",
|
|
212
|
+
"eth_chainId",
|
|
213
|
+
"eth_estimateGas",
|
|
214
|
+
"eth_gasPrice",
|
|
215
|
+
"eth_getBalance",
|
|
216
|
+
"eth_getCode",
|
|
217
|
+
"eth_getStorageAt",
|
|
218
|
+
"eth_getTransactionByHash",
|
|
219
|
+
"eth_getTransactionCount",
|
|
220
|
+
"eth_getTransactionReceipt",
|
|
221
|
+
"net_version",
|
|
222
|
+
"wallet_getCapabilities",
|
|
223
|
+
"wallet_getCallsStatus",
|
|
224
|
+
// Write / sign
|
|
225
|
+
"eth_requestAccounts",
|
|
226
|
+
"eth_sendTransaction",
|
|
227
|
+
"eth_sendRawTransaction",
|
|
228
|
+
"eth_sign",
|
|
229
|
+
"personal_sign",
|
|
230
|
+
"eth_signTypedData",
|
|
231
|
+
"eth_signTypedData_v3",
|
|
232
|
+
"eth_signTypedData_v4",
|
|
233
|
+
"wallet_addEthereumChain",
|
|
234
|
+
"wallet_switchEthereumChain",
|
|
235
|
+
"wallet_sendCalls",
|
|
236
|
+
"wallet_watchAsset"
|
|
237
|
+
]);
|
|
238
|
+
var FORWARDED_PROVIDER_EVENTS = [
|
|
239
|
+
"accountsChanged",
|
|
240
|
+
"chainChanged",
|
|
241
|
+
"connect",
|
|
242
|
+
"disconnect",
|
|
243
|
+
"message"
|
|
244
|
+
];
|
|
245
|
+
function parseBridgeMessage(data) {
|
|
246
|
+
if (!data || typeof data !== "object") return null;
|
|
247
|
+
const msg = data;
|
|
248
|
+
if (msg.protocolVersion !== BRIDGE_PROTOCOL_VERSION) return null;
|
|
249
|
+
switch (msg.type) {
|
|
250
|
+
case "blink:bridge-hello":
|
|
251
|
+
return msg;
|
|
252
|
+
case "blink:wallets-advertised":
|
|
253
|
+
return Array.isArray(msg.wallets) ? msg : null;
|
|
254
|
+
case "blink:rpc-request":
|
|
255
|
+
if (typeof msg.uuid !== "string" || typeof msg.id !== "string" || typeof msg.method !== "string") {
|
|
256
|
+
return null;
|
|
257
|
+
}
|
|
258
|
+
return msg;
|
|
259
|
+
case "blink:rpc-response":
|
|
260
|
+
if (typeof msg.id !== "string") return null;
|
|
261
|
+
return msg;
|
|
262
|
+
case "blink:rpc-event":
|
|
263
|
+
if (typeof msg.uuid !== "string" || typeof msg.event !== "string" || !Array.isArray(msg.args)) {
|
|
264
|
+
return null;
|
|
265
|
+
}
|
|
266
|
+
return msg;
|
|
267
|
+
case "blink:resolve-by-flag":
|
|
268
|
+
if (typeof msg.id !== "string" || !Array.isArray(msg.flags)) return null;
|
|
269
|
+
if (!msg.flags.every((f) => typeof f === "string" && f.length > 0)) return null;
|
|
270
|
+
return msg;
|
|
271
|
+
case "blink:resolve-by-flag-response":
|
|
272
|
+
if (typeof msg.id !== "string") return null;
|
|
273
|
+
if (msg.match !== null && (typeof msg.match !== "object" || !msg.match)) return null;
|
|
274
|
+
return msg;
|
|
275
|
+
default:
|
|
276
|
+
return null;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// src/walletBridge/rpcHost.ts
|
|
281
|
+
function attachRpcHost(options) {
|
|
282
|
+
const { iframeWindow, iframeOrigin, discoverer } = options;
|
|
283
|
+
const log = options.log ?? noopLog;
|
|
284
|
+
if (typeof window === "undefined") {
|
|
285
|
+
return { detach: () => {
|
|
286
|
+
} };
|
|
287
|
+
}
|
|
288
|
+
let detached = false;
|
|
289
|
+
const subscriptions = /* @__PURE__ */ new Map();
|
|
290
|
+
const unsubscribeFromDiscoverer = discoverer.subscribe((snapshot) => {
|
|
291
|
+
if (detached) return;
|
|
292
|
+
advertiseWallets(snapshot);
|
|
293
|
+
});
|
|
294
|
+
function postToIframe(message) {
|
|
295
|
+
if (detached) return;
|
|
296
|
+
try {
|
|
297
|
+
iframeWindow.postMessage(message, iframeOrigin);
|
|
298
|
+
} catch (err) {
|
|
299
|
+
log("postMessage to iframe failed", {
|
|
300
|
+
error: err instanceof Error ? err.message : String(err)
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
function advertiseWallets(snapshot) {
|
|
305
|
+
const wallets = snapshot.map((entry) => ({
|
|
306
|
+
uuid: entry.info.uuid,
|
|
307
|
+
rdns: entry.info.rdns,
|
|
308
|
+
name: entry.info.name,
|
|
309
|
+
icon: entry.info.icon
|
|
310
|
+
}));
|
|
311
|
+
console.info("[blink-bridge:parent] advertising wallets", wallets.map((w) => ({
|
|
312
|
+
rdns: w.rdns,
|
|
313
|
+
name: w.name
|
|
314
|
+
})));
|
|
315
|
+
const message = {
|
|
316
|
+
type: "blink:wallets-advertised",
|
|
317
|
+
protocolVersion: BRIDGE_PROTOCOL_VERSION,
|
|
318
|
+
wallets
|
|
319
|
+
};
|
|
320
|
+
postToIframe(message);
|
|
321
|
+
}
|
|
322
|
+
function ensureSubscription(uuid, provider) {
|
|
323
|
+
if (subscriptions.has(uuid)) return;
|
|
324
|
+
if (typeof provider.on !== "function") {
|
|
325
|
+
subscriptions.set(uuid, { provider, listeners: /* @__PURE__ */ new Map() });
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
const record = { provider, listeners: /* @__PURE__ */ new Map() };
|
|
329
|
+
for (const event of FORWARDED_PROVIDER_EVENTS) {
|
|
330
|
+
const listener = (...args) => {
|
|
331
|
+
const eventMessage = {
|
|
332
|
+
type: "blink:rpc-event",
|
|
333
|
+
protocolVersion: BRIDGE_PROTOCOL_VERSION,
|
|
334
|
+
uuid,
|
|
335
|
+
event,
|
|
336
|
+
args
|
|
337
|
+
};
|
|
338
|
+
postToIframe(eventMessage);
|
|
339
|
+
};
|
|
340
|
+
try {
|
|
341
|
+
provider.on(event, listener);
|
|
342
|
+
record.listeners.set(event, listener);
|
|
343
|
+
} catch (err) {
|
|
344
|
+
log(`provider.on('${event}') threw \u2014 skipping that event`, {
|
|
345
|
+
uuid,
|
|
346
|
+
error: err instanceof Error ? err.message : String(err)
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
subscriptions.set(uuid, record);
|
|
351
|
+
}
|
|
352
|
+
function unsubscribeAll() {
|
|
353
|
+
for (const [, record] of subscriptions) {
|
|
354
|
+
const provider = record.provider;
|
|
355
|
+
if (typeof provider.removeListener !== "function") continue;
|
|
356
|
+
for (const [event, listener] of record.listeners) {
|
|
357
|
+
try {
|
|
358
|
+
provider.removeListener(event, listener);
|
|
359
|
+
} catch {
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
subscriptions.clear();
|
|
364
|
+
}
|
|
365
|
+
function sendError(id, code, message, data) {
|
|
366
|
+
const response = {
|
|
367
|
+
type: "blink:rpc-response",
|
|
368
|
+
protocolVersion: BRIDGE_PROTOCOL_VERSION,
|
|
369
|
+
id,
|
|
370
|
+
error: data === void 0 ? { code, message } : { code, message, data }
|
|
371
|
+
};
|
|
372
|
+
postToIframe(response);
|
|
373
|
+
}
|
|
374
|
+
function sendResult(id, result) {
|
|
375
|
+
const response = {
|
|
376
|
+
type: "blink:rpc-response",
|
|
377
|
+
protocolVersion: BRIDGE_PROTOCOL_VERSION,
|
|
378
|
+
id,
|
|
379
|
+
result
|
|
380
|
+
};
|
|
381
|
+
postToIframe(response);
|
|
382
|
+
}
|
|
383
|
+
const onMessage = (event) => {
|
|
384
|
+
if (detached) return;
|
|
385
|
+
if (event.source !== iframeWindow) return;
|
|
386
|
+
if (event.origin !== iframeOrigin) return;
|
|
387
|
+
const message = parseBridgeMessage(event.data);
|
|
388
|
+
if (!message) return;
|
|
389
|
+
switch (message.type) {
|
|
390
|
+
case "blink:bridge-hello": {
|
|
391
|
+
advertiseWallets(discoverer.list());
|
|
392
|
+
discoverer.requestProviders();
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
case "blink:rpc-request": {
|
|
396
|
+
const { id, uuid, method, params } = message;
|
|
397
|
+
console.info("[blink-bridge:parent] rpc-request", { uuid, method });
|
|
398
|
+
if (!ALLOWED_RPC_METHODS.has(method)) {
|
|
399
|
+
log("rejecting non-allowlisted method", { uuid, method });
|
|
400
|
+
sendError(id, -32601, `Method not allowed: ${method}`);
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
const provider = discoverer.get(uuid);
|
|
404
|
+
if (!provider) {
|
|
405
|
+
log("no provider for uuid", { uuid, method });
|
|
406
|
+
sendError(id, -32602, `Unknown wallet: ${uuid}`);
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
ensureSubscription(uuid, provider);
|
|
410
|
+
provider.request({ method, params }).then((result) => {
|
|
411
|
+
console.info("[blink-bridge:parent] rpc-result", { uuid, method, ok: true });
|
|
412
|
+
sendResult(id, result);
|
|
413
|
+
}).catch((err) => {
|
|
414
|
+
const { code, message: errMessage, data } = normalizeProviderError(err);
|
|
415
|
+
console.info("[blink-bridge:parent] rpc-error", { uuid, method, code, message: errMessage });
|
|
416
|
+
sendError(id, code, errMessage, data);
|
|
417
|
+
});
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
case "blink:resolve-by-flag": {
|
|
421
|
+
const match = resolveByFlag(discoverer.list(), message.flags, log);
|
|
422
|
+
console.info("[blink-bridge:parent] resolveByFlag", {
|
|
423
|
+
flags: message.flags,
|
|
424
|
+
match: match ? { rdns: match.rdns, flag: match.flag } : null
|
|
425
|
+
});
|
|
426
|
+
const response = {
|
|
427
|
+
type: "blink:resolve-by-flag-response",
|
|
428
|
+
protocolVersion: BRIDGE_PROTOCOL_VERSION,
|
|
429
|
+
id: message.id,
|
|
430
|
+
match
|
|
431
|
+
};
|
|
432
|
+
postToIframe(response);
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
case "blink:wallets-advertised":
|
|
436
|
+
case "blink:rpc-response":
|
|
437
|
+
case "blink:rpc-event":
|
|
438
|
+
case "blink:resolve-by-flag-response":
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
};
|
|
442
|
+
window.addEventListener("message", onMessage);
|
|
443
|
+
return {
|
|
444
|
+
detach() {
|
|
445
|
+
if (detached) return;
|
|
446
|
+
detached = true;
|
|
447
|
+
window.removeEventListener("message", onMessage);
|
|
448
|
+
unsubscribeFromDiscoverer();
|
|
449
|
+
unsubscribeAll();
|
|
450
|
+
}
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
function noopLog() {
|
|
454
|
+
}
|
|
455
|
+
function resolveByFlag(snapshot, flags, log) {
|
|
456
|
+
for (const flag of flags) {
|
|
457
|
+
for (const entry of snapshot) {
|
|
458
|
+
let value;
|
|
459
|
+
try {
|
|
460
|
+
value = entry.provider[flag];
|
|
461
|
+
} catch (err) {
|
|
462
|
+
log("provider threw on flag read \u2014 skipping", {
|
|
463
|
+
rdns: entry.info.rdns,
|
|
464
|
+
flag,
|
|
465
|
+
error: err instanceof Error ? err.message : String(err)
|
|
466
|
+
});
|
|
467
|
+
continue;
|
|
468
|
+
}
|
|
469
|
+
if (value) {
|
|
470
|
+
return { rdns: entry.info.rdns, uuid: entry.info.uuid, flag };
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
return null;
|
|
475
|
+
}
|
|
476
|
+
function normalizeProviderError(err) {
|
|
477
|
+
if (err && typeof err === "object") {
|
|
478
|
+
const e = err;
|
|
479
|
+
const code = typeof e.code === "number" ? e.code : -32603;
|
|
480
|
+
const message = typeof e.message === "string" ? e.message : err instanceof Error ? err.message : "Provider error";
|
|
481
|
+
const data = "data" in e ? e.data : void 0;
|
|
482
|
+
return data === void 0 ? { code, message } : { code, message, data };
|
|
483
|
+
}
|
|
484
|
+
return { code: -32603, message: typeof err === "string" ? err : "Provider error" };
|
|
485
|
+
}
|
|
486
|
+
|
|
97
487
|
// src/iframe.ts
|
|
98
488
|
var STYLE_ID = "blink-deposit-styles";
|
|
99
489
|
var CLOSE_DURATION_MS = 280;
|
|
@@ -129,13 +519,26 @@ function createIframe(url, containerElement) {
|
|
|
129
519
|
const iframe = document.createElement("iframe");
|
|
130
520
|
iframe.src = url;
|
|
131
521
|
const iframeOrigin = new URL(url).origin;
|
|
132
|
-
iframe.allow = `publickey-credentials-get ${iframeOrigin}; publickey-credentials-create ${iframeOrigin}`;
|
|
522
|
+
iframe.allow = `publickey-credentials-get ${iframeOrigin}; publickey-credentials-create ${iframeOrigin}; clipboard-write ${iframeOrigin}`;
|
|
133
523
|
const handle = document.createElement("div");
|
|
134
524
|
container.appendChild(handle);
|
|
135
525
|
container.appendChild(iframe);
|
|
136
526
|
overlay.appendChild(container);
|
|
137
527
|
const mountTarget = containerElement ?? document.body;
|
|
138
528
|
mountTarget.appendChild(overlay);
|
|
529
|
+
const discoverer = createWalletDiscoverer();
|
|
530
|
+
let rpcHostHandle = null;
|
|
531
|
+
const attachBridge = () => {
|
|
532
|
+
if (rpcHostHandle) return;
|
|
533
|
+
if (!iframe.contentWindow) return;
|
|
534
|
+
rpcHostHandle = attachRpcHost({
|
|
535
|
+
iframeWindow: iframe.contentWindow,
|
|
536
|
+
iframeOrigin,
|
|
537
|
+
discoverer
|
|
538
|
+
});
|
|
539
|
+
};
|
|
540
|
+
attachBridge();
|
|
541
|
+
iframe.addEventListener("load", attachBridge);
|
|
139
542
|
const savedOverflow = document.body.style.overflow;
|
|
140
543
|
document.body.style.overflow = "hidden";
|
|
141
544
|
const onBackdropClick = (event) => {
|
|
@@ -162,6 +565,7 @@ function createIframe(url, containerElement) {
|
|
|
162
565
|
if (closed) return;
|
|
163
566
|
closed = true;
|
|
164
567
|
removeListeners();
|
|
568
|
+
detachBridge();
|
|
165
569
|
overlay.setAttribute("data-blink-closing", "");
|
|
166
570
|
let removed = false;
|
|
167
571
|
const removeOverlay = () => {
|
|
@@ -174,6 +578,14 @@ function createIframe(url, containerElement) {
|
|
|
174
578
|
container.addEventListener("animationend", removeOverlay, { once: true });
|
|
175
579
|
setTimeout(removeOverlay, CLOSE_DURATION_MS + 50);
|
|
176
580
|
}
|
|
581
|
+
function detachBridge() {
|
|
582
|
+
iframe.removeEventListener("load", attachBridge);
|
|
583
|
+
if (rpcHostHandle) {
|
|
584
|
+
rpcHostHandle.detach();
|
|
585
|
+
rpcHostHandle = null;
|
|
586
|
+
}
|
|
587
|
+
discoverer.destroy();
|
|
588
|
+
}
|
|
177
589
|
return {
|
|
178
590
|
get contentWindow() {
|
|
179
591
|
return iframe.contentWindow;
|
|
@@ -192,6 +604,7 @@ function createIframe(url, containerElement) {
|
|
|
192
604
|
if (!closed) {
|
|
193
605
|
closed = true;
|
|
194
606
|
removeListeners();
|
|
607
|
+
detachBridge();
|
|
195
608
|
overlay.remove();
|
|
196
609
|
unlockScroll();
|
|
197
610
|
}
|
|
@@ -314,8 +727,10 @@ function isValidTokenAddress(value) {
|
|
|
314
727
|
return TOKEN_ADDRESS_RE.test(value) || SOLANA_ADDRESS_RE.test(value);
|
|
315
728
|
}
|
|
316
729
|
function validateDepositRequest(request) {
|
|
317
|
-
if (
|
|
318
|
-
|
|
730
|
+
if (request.amount !== null) {
|
|
731
|
+
if (typeof request.amount !== "number" || !Number.isFinite(request.amount) || request.amount <= 0) {
|
|
732
|
+
throw new DepositError("INVALID_REQUEST", "amount must be a positive number or null.");
|
|
733
|
+
}
|
|
319
734
|
}
|
|
320
735
|
if (!Number.isInteger(request.chainId) || request.chainId <= 0) {
|
|
321
736
|
throw new DepositError("INVALID_REQUEST", "chainId must be a positive integer.");
|