@tangle-network/blueprint-ui 0.3.1 → 0.5.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/dist/chunk-ZKICSKZH.js +57 -0
- package/dist/chunk-ZKICSKZH.js.map +1 -0
- package/dist/detectParentOrigin-BYruoIdc.d.ts +26 -0
- package/dist/iframe/index.d.ts +145 -0
- package/dist/iframe/index.js +557 -0
- package/dist/iframe/index.js.map +1 -0
- package/dist/iframe/testing-index.d.ts +82 -0
- package/dist/iframe/testing-index.js +535 -0
- package/dist/iframe/testing-index.js.map +1 -0
- package/dist/parentBridgeProtocol-BS2zbIvX.d.ts +194 -0
- package/dist/styles.css +3 -0
- package/dist/tangleIframeClient-DES8FDF0.d.ts +121 -0
- package/dist/wallet/index.d.ts +10 -109
- package/dist/wallet/index.js +14 -47
- package/dist/wallet/index.js.map +1 -1
- package/package.json +11 -1
- package/src/iframe/TangleIframeProvider.tsx +172 -0
- package/src/iframe/hooks.ts +234 -0
- package/src/iframe/index.ts +77 -0
- package/src/iframe/tangleIframeClient.test.ts +317 -0
- package/src/iframe/tangleIframeClient.ts +483 -0
- package/src/iframe/testing-index.ts +15 -0
- package/src/iframe/testing.tsx +710 -0
- package/src/wallet/index.ts +11 -0
- package/src/wallet/parentBridgeProtocol.ts +150 -1
- package/src/wallet/parentBridgeProvider.ts +17 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/iframe/testing.tsx"],"sourcesContent":["// Testing harness for iframe blueprints. The promise of the SDK is that\n// publishers can iterate on their UI without running the Tangle Cloud dapp\n// — these utilities are what makes that true.\n\nimport {\n type FC,\n type ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport type { Address } from 'viem';\n\nimport type {\n ServiceSnapshot,\n WalletSnapshot,\n} from './tangleIframeClient';\nimport type {\n CallJobRequest,\n JobInputs,\n JobResultEvent,\n ParentMessage,\n ServiceContextBroadcast,\n ServiceContextJob,\n ServiceContextOperator,\n} from '../wallet/parentBridgeProtocol';\n\nexport type MockWalletInput = Partial<{\n address: Address | null;\n chainId: number;\n isConnected: boolean;\n}>;\n\nexport type MockServiceInput = Partial<{\n blueprintId: string;\n serviceId: string | null;\n operators: readonly ServiceContextOperator[];\n jobs: readonly ServiceContextJob[];\n mode: string | null;\n chain: import('../wallet/parentBridgeProtocol').ChainContext | null;\n}>;\n\n/**\n * Construct a deterministic wallet snapshot for tests. Defaults:\n * connected, vitalik.eth's address, Base Sepolia (84532).\n */\nexport function mockWallet(input: MockWalletInput = {}): WalletSnapshot {\n return {\n address:\n input.address === undefined\n ? '0xd8da6bf26964af9d7eed9e03e53415d37aa96045'\n : input.address,\n chainId: input.chainId ?? 84532,\n isConnected: input.isConnected ?? input.address !== null,\n };\n}\n\n/**\n * Construct a deterministic service snapshot for tests. Defaults: blueprint\n * id `0`, no service deployed yet (serviceId null), single mock operator on\n * the canonical local sidecar URL.\n */\nexport function mockServiceContext(\n input: MockServiceInput = {},\n): ServiceSnapshot {\n return {\n blueprintId: input.blueprintId ?? '0',\n serviceId: input.serviceId === undefined ? null : input.serviceId,\n operators:\n input.operators ?? [\n {\n address: '0x70997970C51812dc3A010C7d01b50e0d17dc79C8',\n rpcAddress: 'http://localhost:8545',\n status: 'active',\n },\n ],\n jobs:\n input.jobs ?? [\n { index: 0, name: 'invoke' },\n ],\n mode: input.mode ?? null,\n chain:\n input.chain === undefined\n ? {\n id: 84532,\n name: 'Base Sepolia',\n rpcUrl: 'https://sepolia.base.org',\n blockExplorerUrl: 'https://sepolia.basescan.org',\n nativeCurrency: { name: 'Sepolia Ether', symbol: 'ETH', decimals: 18 },\n }\n : input.chain,\n };\n}\n\nexport type CallJobHandler = (\n request: CallJobRequest,\n) => Promise<{\n status: 'success' | 'error';\n data?: unknown;\n error?: string;\n /** Streaming chunks emitted in order before the terminal status. */\n chunks?: readonly unknown[];\n}>;\n\ntype HarnessProps = {\n appId?: string;\n wallet?: WalletSnapshot;\n service?: ServiceSnapshot;\n /** Override callJob behavior. Default: returns a static `{ ok: true }`. */\n onCallJob?: CallJobHandler;\n /** Surface a floating debug panel that lets the developer flip state at runtime. */\n showDebugPanel?: boolean;\n children: ReactNode;\n};\n\n/**\n * Drop-in parent simulator for tests + storybook + standalone dev. Wraps\n * children in a fake parent that:\n *\n * - Acks the iframe's handshake immediately\n * - Broadcasts the configured wallet + service context on mount\n * - Intercepts `callJob` requests and routes them through `onCallJob`\n * - (Optional) Mounts a floating debug panel so the developer can\n * mutate state at runtime: change account, switch chain, set\n * serviceId, fire a custom job\n *\n * The harness runs in the same JS context as the iframe app — there's no\n * cross-frame postMessage, just same-window event dispatch. That keeps it\n * fully synchronous + assertable, but the messages still flow through the\n * exact same protocol surface the production bridge uses.\n *\n * Usage:\n *\n * <TangleParentHarness wallet={mockWallet()} service={mockServiceContext()}>\n * <TangleIframeProvider appId=\"my-app\" mode=\"bridge\" parentOrigin=\"harness://\">\n * <App />\n * </TangleIframeProvider>\n * </TangleParentHarness>\n *\n * Set `mode=\"bridge\"` + `parentOrigin=\"harness://\"` on the provider so it\n * matches the harness's synthetic origin. In production, use `mode=\"auto\"`\n * (the default).\n */\nexport const TangleParentHarness: FC<HarnessProps> = ({\n appId = 'harness',\n wallet = mockWallet(),\n service = mockServiceContext(),\n onCallJob,\n showDebugPanel = false,\n children,\n}) => {\n const [currentWallet, setCurrentWallet] = useState<WalletSnapshot>(wallet);\n const [currentService, setCurrentService] =\n useState<ServiceSnapshot>(service);\n const [callLog, setCallLog] = useState<CallJobRequest[]>([]);\n const callJobHandler = useRef<CallJobHandler | undefined>(onCallJob);\n callJobHandler.current = onCallJob;\n const seenHandshake = useRef(false);\n\n // Listen for iframe → \"parent\" messages. Since the harness shares the\n // window, `window.postMessage` with the synthetic origin is the easiest\n // wire — the iframe SDK posts to `window.parent`, which in same-window\n // mode IS this listener.\n useEffect(() => {\n const reply = (message: ParentMessage) => {\n window.dispatchEvent(\n new MessageEvent('message', {\n data: message,\n origin: HARNESS_ORIGIN,\n }),\n );\n };\n\n const broadcast = () => {\n const broadcastMsg: ServiceContextBroadcast = {\n kind: 'tangle.app.serviceContext',\n blueprintId: currentService.blueprintId ?? '0',\n serviceId: currentService.serviceId,\n operators: currentService.operators,\n jobs: currentService.jobs,\n mode: currentService.mode,\n ...(currentService.chain !== null\n ? { chain: currentService.chain }\n : {}),\n };\n reply(broadcastMsg);\n // Also broadcast wallet — combined into accountChanged + chainChanged.\n reply({\n kind: 'tangle.app.accountChanged',\n account: currentWallet.address,\n });\n if (currentWallet.chainId !== null) {\n reply({\n kind: 'tangle.app.chainChanged',\n chainId: currentWallet.chainId,\n });\n }\n };\n\n const handler = async (event: MessageEvent) => {\n // The iframe posts via `window.parent.postMessage(msg, parentOrigin)`.\n // In same-window mode, that fires a message event on this same window\n // with origin = parentOrigin. Filter out events the harness itself\n // dispatched (origin === HARNESS_ORIGIN) — those are replies.\n if (event.origin === HARNESS_ORIGIN) return;\n const data = event.data;\n if (typeof data !== 'object' || data === null) return;\n const message = data as { kind?: string; correlationId?: string };\n\n switch (message.kind) {\n case 'tangle.app.handshake': {\n if (!seenHandshake.current) {\n seenHandshake.current = true;\n reply({\n kind: 'tangle.app.handshakeAck',\n appId,\n protocolVersion: '1',\n });\n broadcast();\n }\n return;\n }\n case 'tangle.app.readAccount': {\n if (typeof message.correlationId !== 'string') return;\n reply({\n kind: 'tangle.app.readAccountResult',\n correlationId: message.correlationId,\n ok: true,\n data: {\n account:\n currentWallet.address ??\n ('0x0000000000000000000000000000000000000000' as Address),\n chainId: currentWallet.chainId ?? 0,\n },\n });\n return;\n }\n case 'tangle.app.callJob': {\n if (typeof message.correlationId !== 'string') return;\n const request = message as unknown as CallJobRequest;\n setCallLog((prev) => [...prev, request]);\n // Default behavior when no handler: emit a single `success` with\n // a echo of the inputs so UIs render *something* in dev mode.\n const handler = callJobHandler.current;\n if (!handler) {\n const result: JobResultEvent = {\n kind: 'tangle.app.jobResult',\n correlationId: request.correlationId,\n status: 'success',\n data: { echo: request.inputs },\n };\n reply(result);\n return;\n }\n try {\n const outcome = await handler(request);\n for (const chunk of outcome.chunks ?? []) {\n reply({\n kind: 'tangle.app.jobResult',\n correlationId: request.correlationId,\n status: 'streaming',\n chunk,\n });\n }\n reply({\n kind: 'tangle.app.jobResult',\n correlationId: request.correlationId,\n status: outcome.status,\n ...(outcome.data !== undefined ? { data: outcome.data } : {}),\n ...(outcome.error !== undefined ? { error: outcome.error } : {}),\n });\n } catch (err) {\n reply({\n kind: 'tangle.app.jobResult',\n correlationId: request.correlationId,\n status: 'error',\n error: err instanceof Error ? err.message : String(err),\n });\n }\n return;\n }\n // Wallet ops respond optimistically — tests that want to assert\n // specific signatures should pre-set them via the dev handler.\n case 'tangle.app.signMessage': {\n if (typeof message.correlationId !== 'string') return;\n reply({\n kind: 'tangle.app.signMessageResult',\n correlationId: message.correlationId,\n ok: true,\n data: { signature: '0xdeadbeef' as `0x${string}` },\n });\n return;\n }\n case 'tangle.app.signTypedData': {\n if (typeof message.correlationId !== 'string') return;\n // The harness signs deterministically — production parents show\n // an approval modal first. Tests that need to assert the\n // typed-data payload should inspect callLog (extend later if\n // needed) or pass a custom onSignTypedData handler.\n reply({\n kind: 'tangle.app.signTypedDataResult',\n correlationId: message.correlationId,\n ok: true,\n data: {\n signature: ('0x' + '11'.repeat(65)) as `0x${string}`,\n },\n });\n return;\n }\n case 'tangle.app.signTransaction': {\n if (typeof message.correlationId !== 'string') return;\n reply({\n kind: 'tangle.app.signTransactionResult',\n correlationId: message.correlationId,\n ok: true,\n data: { txHash: ('0x' + '00'.repeat(32)) as `0x${string}` },\n });\n return;\n }\n case 'tangle.app.switchChain': {\n if (\n typeof message.correlationId !== 'string' ||\n typeof (message as unknown as { chainId?: number }).chainId !== 'number'\n ) {\n return;\n }\n const chainId = (message as unknown as { chainId: number }).chainId;\n setCurrentWallet((w) => ({ ...w, chainId }));\n reply({\n kind: 'tangle.app.switchChainResult',\n correlationId: message.correlationId,\n ok: true,\n data: { chainId },\n });\n return;\n }\n }\n };\n window.addEventListener('message', handler);\n return () => window.removeEventListener('message', handler);\n }, [appId, currentWallet, currentService]);\n\n // Re-broadcast when state changes.\n useEffect(() => {\n if (!seenHandshake.current) return;\n window.dispatchEvent(\n new MessageEvent('message', {\n data: {\n kind: 'tangle.app.accountChanged',\n account: currentWallet.address,\n },\n origin: HARNESS_ORIGIN,\n }),\n );\n }, [currentWallet.address]);\n\n useEffect(() => {\n if (!seenHandshake.current || currentWallet.chainId === null) return;\n window.dispatchEvent(\n new MessageEvent('message', {\n data: {\n kind: 'tangle.app.chainChanged',\n chainId: currentWallet.chainId,\n },\n origin: HARNESS_ORIGIN,\n }),\n );\n }, [currentWallet.chainId]);\n\n useEffect(() => {\n if (!seenHandshake.current) return;\n window.dispatchEvent(\n new MessageEvent('message', {\n data: {\n kind: 'tangle.app.serviceContext',\n blueprintId: currentService.blueprintId ?? '0',\n serviceId: currentService.serviceId,\n operators: currentService.operators,\n jobs: currentService.jobs,\n mode: currentService.mode,\n ...(currentService.chain !== null\n ? { chain: currentService.chain }\n : {}),\n },\n origin: HARNESS_ORIGIN,\n }),\n );\n }, [currentService]);\n\n const debugApi = useMemo(\n () => ({\n setWallet: setCurrentWallet,\n setService: setCurrentService,\n callLog,\n }),\n [callLog],\n );\n\n return (\n <>\n {children}\n {showDebugPanel && <DebugPanel api={debugApi} />}\n </>\n );\n};\n\n/**\n * Synthetic origin every harness instance uses. Stable across tests so the\n * iframe SDK + the harness can pin to the same string.\n */\nexport const HARNESS_ORIGIN = 'harness://tangle.local';\n\n// ── Debug panel ──────────────────────────────────────────────────────────────\n\nconst DebugPanel: FC<{\n api: {\n setWallet: (w: WalletSnapshot | ((prev: WalletSnapshot) => WalletSnapshot)) => void;\n setService: (\n s: ServiceSnapshot | ((prev: ServiceSnapshot) => ServiceSnapshot),\n ) => void;\n callLog: readonly CallJobRequest[];\n };\n}> = ({ api }) => {\n const [open, setOpen] = useState(true);\n const [tab, setTab] = useState<'wallet' | 'service' | 'log'>('wallet');\n if (!open) {\n return (\n <button\n type=\"button\"\n onClick={() => setOpen(true)}\n style={debugStyles.collapsedTrigger}\n >\n Debug\n </button>\n );\n }\n return (\n <div style={debugStyles.panel}>\n <header style={debugStyles.header}>\n <strong style={{ fontSize: 11 }}>TANGLE DEV HARNESS</strong>\n <button\n type=\"button\"\n onClick={() => setOpen(false)}\n style={debugStyles.closeButton}\n aria-label=\"Close debug panel\"\n >\n ×\n </button>\n </header>\n <nav style={debugStyles.tabs}>\n {(['wallet', 'service', 'log'] as const).map((t) => (\n <button\n key={t}\n type=\"button\"\n onClick={() => setTab(t)}\n style={{\n ...debugStyles.tab,\n ...(tab === t ? debugStyles.tabActive : {}),\n }}\n >\n {t}\n </button>\n ))}\n </nav>\n <div style={debugStyles.body}>\n {tab === 'wallet' && <WalletTab api={api} />}\n {tab === 'service' && <ServiceTab api={api} />}\n {tab === 'log' && <CallLogTab callLog={api.callLog} />}\n </div>\n </div>\n );\n};\n\nconst WalletTab: FC<{\n api: { setWallet: (w: WalletSnapshot | ((prev: WalletSnapshot) => WalletSnapshot)) => void };\n}> = ({ api }) => {\n const [address, setAddressInput] = useState(\n '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',\n );\n const [chainId, setChainIdInput] = useState('84532');\n const applyConnect = useCallback(() => {\n api.setWallet({\n address: address as Address,\n chainId: Number(chainId) || null,\n isConnected: true,\n });\n }, [address, chainId, api]);\n const disconnect = useCallback(() => {\n api.setWallet({ address: null, chainId: null, isConnected: false });\n }, [api]);\n return (\n <div>\n <label style={debugStyles.label}>address</label>\n <input\n value={address}\n onChange={(e) => setAddressInput(e.target.value)}\n style={debugStyles.input}\n />\n <label style={debugStyles.label}>chain id</label>\n <input\n value={chainId}\n onChange={(e) => setChainIdInput(e.target.value)}\n style={debugStyles.input}\n />\n <div style={debugStyles.buttonRow}>\n <button type=\"button\" onClick={applyConnect} style={debugStyles.primary}>\n Set connected\n </button>\n <button type=\"button\" onClick={disconnect} style={debugStyles.secondary}>\n Disconnect\n </button>\n </div>\n </div>\n );\n};\n\nconst ServiceTab: FC<{\n api: {\n setService: (\n s: ServiceSnapshot | ((prev: ServiceSnapshot) => ServiceSnapshot),\n ) => void;\n };\n}> = ({ api }) => {\n const [serviceId, setServiceIdInput] = useState('1');\n const [blueprintId, setBlueprintIdInput] = useState('0');\n const apply = useCallback(() => {\n api.setService((prev) => ({\n ...prev,\n serviceId: serviceId || null,\n blueprintId,\n }));\n }, [api, serviceId, blueprintId]);\n const clearService = useCallback(() => {\n api.setService((prev) => ({ ...prev, serviceId: null }));\n }, [api]);\n return (\n <div>\n <label style={debugStyles.label}>blueprint id</label>\n <input\n value={blueprintId}\n onChange={(e) => setBlueprintIdInput(e.target.value)}\n style={debugStyles.input}\n />\n <label style={debugStyles.label}>service id (empty = not deployed)</label>\n <input\n value={serviceId}\n onChange={(e) => setServiceIdInput(e.target.value)}\n style={debugStyles.input}\n />\n <div style={debugStyles.buttonRow}>\n <button type=\"button\" onClick={apply} style={debugStyles.primary}>\n Apply\n </button>\n <button type=\"button\" onClick={clearService} style={debugStyles.secondary}>\n Clear service\n </button>\n </div>\n </div>\n );\n};\n\nconst CallLogTab: FC<{ callLog: readonly CallJobRequest[] }> = ({ callLog }) => {\n if (callLog.length === 0) {\n return <p style={debugStyles.empty}>No callJob requests yet.</p>;\n }\n return (\n <ol style={debugStyles.log}>\n {callLog.map((entry) => (\n <li key={entry.correlationId} style={debugStyles.logEntry}>\n <strong>job {entry.jobIndex}</strong>\n <pre style={debugStyles.pre}>\n {JSON.stringify(entry.inputs, null, 2)}\n </pre>\n </li>\n ))}\n </ol>\n );\n};\n\n// Inline styles keep the harness style-system-agnostic — consumers may not\n// ship Tailwind, and the panel shouldn't add a dependency.\nconst debugStyles = {\n panel: {\n position: 'fixed' as const,\n right: 12,\n top: 12,\n width: 280,\n zIndex: 99999,\n background: '#0b0b14',\n color: '#fff',\n border: '1px solid #3a3a52',\n borderRadius: 10,\n boxShadow: '0 14px 32px rgba(0,0,0,0.4)',\n fontFamily:\n 'ui-monospace, SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", monospace',\n fontSize: 12,\n },\n header: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n padding: '8px 10px',\n borderBottom: '1px solid #2a2a3e',\n },\n closeButton: {\n background: 'none',\n border: 'none',\n color: '#fff',\n fontSize: 18,\n cursor: 'pointer',\n lineHeight: 1,\n },\n tabs: {\n display: 'flex',\n borderBottom: '1px solid #2a2a3e',\n },\n tab: {\n flex: 1,\n background: 'none',\n border: 'none',\n color: '#a0a0c0',\n padding: '6px 8px',\n cursor: 'pointer',\n fontSize: 11,\n textTransform: 'uppercase' as const,\n },\n tabActive: {\n color: '#fff',\n borderBottom: '2px solid #818cf8',\n },\n body: {\n padding: 10,\n maxHeight: 320,\n overflow: 'auto' as const,\n },\n label: {\n display: 'block',\n color: '#a0a0c0',\n fontSize: 10,\n marginBottom: 4,\n marginTop: 6,\n textTransform: 'uppercase' as const,\n },\n input: {\n width: '100%',\n background: '#15152a',\n border: '1px solid #2a2a3e',\n color: '#fff',\n padding: '6px 8px',\n borderRadius: 4,\n fontFamily: 'inherit',\n fontSize: 11,\n boxSizing: 'border-box' as const,\n },\n buttonRow: { display: 'flex', gap: 6, marginTop: 8 },\n primary: {\n flex: 1,\n background: '#4f46e5',\n color: '#fff',\n border: 'none',\n padding: '6px 8px',\n borderRadius: 4,\n cursor: 'pointer',\n fontSize: 11,\n fontFamily: 'inherit',\n },\n secondary: {\n flex: 1,\n background: 'transparent',\n color: '#a0a0c0',\n border: '1px solid #3a3a52',\n padding: '6px 8px',\n borderRadius: 4,\n cursor: 'pointer',\n fontSize: 11,\n fontFamily: 'inherit',\n },\n collapsedTrigger: {\n position: 'fixed' as const,\n right: 12,\n top: 12,\n zIndex: 99999,\n padding: '6px 10px',\n background: '#0b0b14',\n border: '1px solid #3a3a52',\n color: '#fff',\n borderRadius: 6,\n fontFamily: 'inherit',\n fontSize: 11,\n cursor: 'pointer',\n },\n log: { listStyle: 'none', padding: 0, margin: 0 },\n logEntry: {\n padding: 6,\n borderBottom: '1px solid #2a2a3e',\n fontSize: 11,\n },\n pre: {\n margin: '4px 0 0',\n color: '#a0a0c0',\n fontSize: 10,\n whiteSpace: 'pre-wrap' as const,\n wordBreak: 'break-word' as const,\n },\n empty: { color: '#a0a0c0', fontSize: 11, margin: 0 },\n} as const;\n\nexport type { JobInputs };\n"],"mappings":"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","names":["handler"]}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { Address, Hex } from 'viem';
|
|
2
|
+
|
|
3
|
+
declare const TANGLE_IFRAME_PROTOCOL_VERSION: "1";
|
|
4
|
+
declare const TANGLE_IFRAME_PROTOCOL_PREFIX = "tangle.app.";
|
|
5
|
+
type HandshakeRequest = {
|
|
6
|
+
kind: 'tangle.app.handshake';
|
|
7
|
+
appId: string;
|
|
8
|
+
version: typeof TANGLE_IFRAME_PROTOCOL_VERSION;
|
|
9
|
+
};
|
|
10
|
+
type ReadAccountRequest = {
|
|
11
|
+
kind: 'tangle.app.readAccount';
|
|
12
|
+
correlationId: string;
|
|
13
|
+
};
|
|
14
|
+
type SwitchChainRequest = {
|
|
15
|
+
kind: 'tangle.app.switchChain';
|
|
16
|
+
correlationId: string;
|
|
17
|
+
chainId: number;
|
|
18
|
+
};
|
|
19
|
+
type SignMessageRequest = {
|
|
20
|
+
kind: 'tangle.app.signMessage';
|
|
21
|
+
correlationId: string;
|
|
22
|
+
chainId: number;
|
|
23
|
+
message: string;
|
|
24
|
+
};
|
|
25
|
+
type SignTransactionRequest = {
|
|
26
|
+
kind: 'tangle.app.signTransaction';
|
|
27
|
+
correlationId: string;
|
|
28
|
+
chainId: number;
|
|
29
|
+
to: Address;
|
|
30
|
+
data: Hex;
|
|
31
|
+
value?: string;
|
|
32
|
+
};
|
|
33
|
+
type SignTypedDataRequest = {
|
|
34
|
+
kind: 'tangle.app.signTypedData';
|
|
35
|
+
correlationId: string;
|
|
36
|
+
chainId: number;
|
|
37
|
+
domain: Readonly<{
|
|
38
|
+
name?: string;
|
|
39
|
+
version?: string;
|
|
40
|
+
chainId?: number;
|
|
41
|
+
verifyingContract?: Address;
|
|
42
|
+
salt?: Hex;
|
|
43
|
+
}>;
|
|
44
|
+
/** EIP-712 types map; do NOT include the EIP712Domain entry (the parent
|
|
45
|
+
* injects it derived from `domain`). */
|
|
46
|
+
types: Readonly<Record<string, ReadonlyArray<{
|
|
47
|
+
name: string;
|
|
48
|
+
type: string;
|
|
49
|
+
}>>>;
|
|
50
|
+
/** Top-level type name in `types` whose values appear in `message`. */
|
|
51
|
+
primaryType: string;
|
|
52
|
+
/** The actual typed-data values. Shape matches `types[primaryType]`. */
|
|
53
|
+
message: Readonly<Record<string, unknown>>;
|
|
54
|
+
};
|
|
55
|
+
type HandshakeAck = {
|
|
56
|
+
kind: 'tangle.app.handshakeAck';
|
|
57
|
+
appId: string;
|
|
58
|
+
protocolVersion: typeof TANGLE_IFRAME_PROTOCOL_VERSION;
|
|
59
|
+
};
|
|
60
|
+
type ResultEnvelope<T> = {
|
|
61
|
+
correlationId: string;
|
|
62
|
+
} & ({
|
|
63
|
+
ok: true;
|
|
64
|
+
data: T;
|
|
65
|
+
} | {
|
|
66
|
+
ok: false;
|
|
67
|
+
error: string;
|
|
68
|
+
});
|
|
69
|
+
type ReadAccountResult = {
|
|
70
|
+
kind: 'tangle.app.readAccountResult';
|
|
71
|
+
} & ResultEnvelope<{
|
|
72
|
+
account: Address;
|
|
73
|
+
chainId: number;
|
|
74
|
+
}>;
|
|
75
|
+
type SwitchChainResult = {
|
|
76
|
+
kind: 'tangle.app.switchChainResult';
|
|
77
|
+
} & ResultEnvelope<{
|
|
78
|
+
chainId: number;
|
|
79
|
+
}>;
|
|
80
|
+
type SignMessageResult = {
|
|
81
|
+
kind: 'tangle.app.signMessageResult';
|
|
82
|
+
} & ResultEnvelope<{
|
|
83
|
+
signature: Hex;
|
|
84
|
+
}>;
|
|
85
|
+
type SignTransactionResult = {
|
|
86
|
+
kind: 'tangle.app.signTransactionResult';
|
|
87
|
+
} & ResultEnvelope<{
|
|
88
|
+
txHash: Hex;
|
|
89
|
+
}>;
|
|
90
|
+
type SignTypedDataResult = {
|
|
91
|
+
kind: 'tangle.app.signTypedDataResult';
|
|
92
|
+
} & ResultEnvelope<{
|
|
93
|
+
signature: Hex;
|
|
94
|
+
}>;
|
|
95
|
+
type AccountChanged = {
|
|
96
|
+
kind: 'tangle.app.accountChanged';
|
|
97
|
+
account: Address | null;
|
|
98
|
+
};
|
|
99
|
+
type ChainChanged = {
|
|
100
|
+
kind: 'tangle.app.chainChanged';
|
|
101
|
+
chainId: number;
|
|
102
|
+
};
|
|
103
|
+
type ServiceContextOperator = {
|
|
104
|
+
readonly address: Address;
|
|
105
|
+
readonly rpcAddress: string | undefined;
|
|
106
|
+
readonly status: 'active' | 'inactive' | 'unknown';
|
|
107
|
+
};
|
|
108
|
+
type ServiceContextJob = {
|
|
109
|
+
readonly index: number;
|
|
110
|
+
readonly name: string;
|
|
111
|
+
readonly inputSchema?: unknown;
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* Chain configuration the parent broadcasts to the iframe along with
|
|
115
|
+
* service context. Iframes use this to build a `viem` public client for
|
|
116
|
+
* READ-ONLY queries (`useTanglePublicClient` is the convenience hook).
|
|
117
|
+
*
|
|
118
|
+
* Iframes can ignore this and roll their own RPC config — particularly
|
|
119
|
+
* when they need to read from chains OTHER than the active one (e.g. a
|
|
120
|
+
* trading dapp pulling oracle data from mainnet while the active service
|
|
121
|
+
* lives on Base Sepolia). The injected client is a hint, not a constraint.
|
|
122
|
+
*
|
|
123
|
+
* `rpcUrl` is the public RPC the parent uses, NOT a wallet RPC. Iframes
|
|
124
|
+
* cannot sign or submit with this URL; signing always routes upstream via
|
|
125
|
+
* the bridge.
|
|
126
|
+
*/
|
|
127
|
+
type ChainContext = {
|
|
128
|
+
readonly id: number;
|
|
129
|
+
readonly name: string;
|
|
130
|
+
readonly rpcUrl: string;
|
|
131
|
+
/** Block-explorer base URL — useful for rendering tx links. */
|
|
132
|
+
readonly blockExplorerUrl?: string;
|
|
133
|
+
/** Native currency metadata for cost displays. */
|
|
134
|
+
readonly nativeCurrency?: {
|
|
135
|
+
readonly name: string;
|
|
136
|
+
readonly symbol: string;
|
|
137
|
+
readonly decimals: number;
|
|
138
|
+
};
|
|
139
|
+
};
|
|
140
|
+
type ServiceContextBroadcast = {
|
|
141
|
+
kind: 'tangle.app.serviceContext';
|
|
142
|
+
readonly blueprintId: string;
|
|
143
|
+
readonly serviceId: string | null;
|
|
144
|
+
readonly operators: readonly ServiceContextOperator[];
|
|
145
|
+
readonly jobs: readonly ServiceContextJob[];
|
|
146
|
+
readonly mode: string | null;
|
|
147
|
+
/** Active chain the parent is connected to; iframes can build a viem
|
|
148
|
+
* publicClient against this for convenience. Optional for backwards
|
|
149
|
+
* compatibility with parents that haven't been upgraded yet. */
|
|
150
|
+
readonly chain?: ChainContext;
|
|
151
|
+
};
|
|
152
|
+
type JobInputs = Readonly<Record<string, unknown>>;
|
|
153
|
+
type CallJobRequest = {
|
|
154
|
+
kind: 'tangle.app.callJob';
|
|
155
|
+
correlationId: string;
|
|
156
|
+
/** Job index within the blueprint, e.g. 0 for the primary entry-point. */
|
|
157
|
+
jobIndex: number;
|
|
158
|
+
/** Free-form inputs validated by the parent against the on-chain ABI. */
|
|
159
|
+
inputs: JobInputs;
|
|
160
|
+
/**
|
|
161
|
+
* Whether the publisher wants intermediate progress (streaming chunks)
|
|
162
|
+
* or just the terminal result. Streaming jobs (LLM generation, video
|
|
163
|
+
* encode) opt in; one-shots (embeddings, classifications) don't.
|
|
164
|
+
*/
|
|
165
|
+
stream?: boolean;
|
|
166
|
+
};
|
|
167
|
+
type JobResultStatus = 'pending' | 'streaming' | 'success' | 'error';
|
|
168
|
+
type JobResultEvent = {
|
|
169
|
+
kind: 'tangle.app.jobResult';
|
|
170
|
+
correlationId: string;
|
|
171
|
+
status: JobResultStatus;
|
|
172
|
+
/** Present on `streaming` and `success`. Shape is publisher-defined. */
|
|
173
|
+
data?: unknown;
|
|
174
|
+
/** Present on `streaming` only — incremental chunk for live UI. */
|
|
175
|
+
chunk?: unknown;
|
|
176
|
+
/** Present on `error`. Human-readable. */
|
|
177
|
+
error?: string;
|
|
178
|
+
/** Optional progress metadata (e.g. `{ percent: 0.42, eta_ms: 8000 }`). */
|
|
179
|
+
progress?: {
|
|
180
|
+
readonly percent?: number;
|
|
181
|
+
readonly eta_ms?: number;
|
|
182
|
+
};
|
|
183
|
+
};
|
|
184
|
+
type ParentMessage = HandshakeAck | ReadAccountResult | SwitchChainResult | SignMessageResult | SignTransactionResult | SignTypedDataResult | AccountChanged | ChainChanged | ServiceContextBroadcast | JobResultEvent;
|
|
185
|
+
type IframeRequest = HandshakeRequest | ReadAccountRequest | SwitchChainRequest | SignMessageRequest | SignTransactionRequest | SignTypedDataRequest | CallJobRequest;
|
|
186
|
+
declare const NO_WALLET_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
187
|
+
/**
|
|
188
|
+
* Cryptographically-random ASCII correlation id matching the parent's
|
|
189
|
+
* validator regex (`/^[\w.\-:]+$/`, max length 128). The connector keeps a
|
|
190
|
+
* Map<correlationId, Resolver> so each request resolves independently.
|
|
191
|
+
*/
|
|
192
|
+
declare function makeCorrelationId(prefix: string): string;
|
|
193
|
+
|
|
194
|
+
export { type AccountChanged as A, type CallJobRequest as C, type HandshakeAck as H, type IframeRequest as I, type JobInputs as J, NO_WALLET_ADDRESS as N, type ParentMessage as P, type ReadAccountRequest as R, type ServiceContextBroadcast as S, TANGLE_IFRAME_PROTOCOL_PREFIX as T, type ChainChanged as a, type ChainContext as b, type HandshakeRequest as c, type JobResultEvent as d, type JobResultStatus as e, type ReadAccountResult as f, type ServiceContextJob as g, type ServiceContextOperator as h, type SignMessageRequest as i, type SignMessageResult as j, type SignTransactionRequest as k, type SignTransactionResult as l, type SignTypedDataRequest as m, type SignTypedDataResult as n, type SwitchChainRequest as o, type SwitchChainResult as p, TANGLE_IFRAME_PROTOCOL_VERSION as q, makeCorrelationId as r };
|
package/dist/styles.css
CHANGED
|
@@ -246,6 +246,7 @@
|
|
|
246
246
|
.tracking-wider{--un-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider);}
|
|
247
247
|
.font-medium{--un-font-weight:var(--fontWeight-medium);font-weight:var(--fontWeight-medium);}
|
|
248
248
|
.font-semibold{--un-font-weight:var(--fontWeight-semibold);font-weight:var(--fontWeight-semibold);}
|
|
249
|
+
.tab{-moz-tab-size:4;-o-tab-size:4;tab-size:4;}
|
|
249
250
|
.mx-auto{margin-inline:auto;}
|
|
250
251
|
.my-2{margin-block:calc(var(--spacing) * 2);}
|
|
251
252
|
.mb-2{margin-bottom:calc(var(--spacing) * 2);}
|
|
@@ -403,6 +404,7 @@
|
|
|
403
404
|
.inline{display:inline;}
|
|
404
405
|
.block{display:block;}
|
|
405
406
|
.hidden{display:none;}
|
|
407
|
+
.collapse{visibility:collapse;}
|
|
406
408
|
.cursor-pointer{cursor:pointer;}
|
|
407
409
|
.\[\&_svg\]\:pointer-events-none svg,
|
|
408
410
|
.pointer-events-none{pointer-events:none;}
|
|
@@ -458,6 +460,7 @@
|
|
|
458
460
|
.absolute{position:absolute;}
|
|
459
461
|
.fixed{position:fixed;}
|
|
460
462
|
.relative{position:relative;}
|
|
463
|
+
.static{position:static;}
|
|
461
464
|
.z-50{z-index:50;}
|
|
462
465
|
.overflow-auto{overflow:auto;}
|
|
463
466
|
.overflow-hidden{overflow:hidden;}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { Address, Hex } from 'viem';
|
|
2
|
+
import { h as ServiceContextOperator, g as ServiceContextJob, b as ChainContext, e as JobResultStatus, m as SignTypedDataRequest, J as JobInputs } from './parentBridgeProtocol-BS2zbIvX.js';
|
|
3
|
+
|
|
4
|
+
type WalletSnapshot = {
|
|
5
|
+
readonly address: Address | null;
|
|
6
|
+
readonly chainId: number | null;
|
|
7
|
+
readonly isConnected: boolean;
|
|
8
|
+
};
|
|
9
|
+
type ServiceSnapshot = {
|
|
10
|
+
readonly blueprintId: string | null;
|
|
11
|
+
readonly serviceId: string | null;
|
|
12
|
+
readonly operators: readonly ServiceContextOperator[];
|
|
13
|
+
readonly jobs: readonly ServiceContextJob[];
|
|
14
|
+
readonly mode: string | null;
|
|
15
|
+
/** Chain context broadcast by the parent — drives `useTanglePublicClient`.
|
|
16
|
+
* `null` when the parent hasn't sent one (older parent or dev mode). */
|
|
17
|
+
readonly chain: ChainContext | null;
|
|
18
|
+
};
|
|
19
|
+
type JobInvocation = {
|
|
20
|
+
readonly correlationId: string;
|
|
21
|
+
readonly status: JobResultStatus;
|
|
22
|
+
readonly data?: unknown;
|
|
23
|
+
readonly chunks: readonly unknown[];
|
|
24
|
+
readonly error?: string;
|
|
25
|
+
readonly progress?: {
|
|
26
|
+
readonly percent?: number;
|
|
27
|
+
readonly eta_ms?: number;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
type ClientEventMap = {
|
|
31
|
+
wallet: WalletSnapshot;
|
|
32
|
+
service: ServiceSnapshot;
|
|
33
|
+
job: JobInvocation;
|
|
34
|
+
};
|
|
35
|
+
type Listener<K extends keyof ClientEventMap> = (value: ClientEventMap[K]) => void;
|
|
36
|
+
type TangleIframeClientOptions = {
|
|
37
|
+
/**
|
|
38
|
+
* Origin of the parent dapp. The client posts every message with this
|
|
39
|
+
* exact `targetOrigin` and rejects inbound messages from any other origin.
|
|
40
|
+
* Pass `'*'` only in dev — production must pin to the real parent
|
|
41
|
+
* (`https://cloud.tangle.tools` etc.).
|
|
42
|
+
*/
|
|
43
|
+
parentOrigin: string;
|
|
44
|
+
/**
|
|
45
|
+
* Stable identifier for this iframe app. The parent surfaces it in
|
|
46
|
+
* handshake logs + uses it for permission scoping.
|
|
47
|
+
*/
|
|
48
|
+
appId: string;
|
|
49
|
+
/**
|
|
50
|
+
* Per-request timeout. Defaults to 60s — long enough for a user to
|
|
51
|
+
* read + approve a signing prompt in the parent. Long-running jobs
|
|
52
|
+
* stream progress events; the request "completes" only on terminal
|
|
53
|
+
* status, so the timeout protects against parents that drop replies
|
|
54
|
+
* entirely.
|
|
55
|
+
*/
|
|
56
|
+
requestTimeoutMs?: number;
|
|
57
|
+
};
|
|
58
|
+
declare class TangleIframeClient {
|
|
59
|
+
private readonly options;
|
|
60
|
+
private wallet;
|
|
61
|
+
private service;
|
|
62
|
+
private handshakeAcked;
|
|
63
|
+
private handshakeWaiters;
|
|
64
|
+
private installed;
|
|
65
|
+
private listeners;
|
|
66
|
+
private pendingJobs;
|
|
67
|
+
constructor(options: TangleIframeClientOptions);
|
|
68
|
+
/** Wire the global message listener + initial handshake. Idempotent. */
|
|
69
|
+
install(): void;
|
|
70
|
+
uninstall(): void;
|
|
71
|
+
getWallet(): WalletSnapshot;
|
|
72
|
+
getService(): ServiceSnapshot;
|
|
73
|
+
subscribe<K extends keyof ClientEventMap>(event: K, listener: Listener<K>): () => void;
|
|
74
|
+
signMessage(message: string): Promise<Hex>;
|
|
75
|
+
sendTransaction(tx: {
|
|
76
|
+
to: Address;
|
|
77
|
+
data: Hex;
|
|
78
|
+
value?: bigint;
|
|
79
|
+
}): Promise<Hex>;
|
|
80
|
+
switchChain(chainId: number): Promise<number>;
|
|
81
|
+
/**
|
|
82
|
+
* EIP-712 typed-data signing. The parent renders the typed-data fields in
|
|
83
|
+
* its approval modal; the user audits what they're signing. Use for
|
|
84
|
+
* operator envelopes, off-chain attestations, anything that needs a
|
|
85
|
+
* signature outside the standard blueprint-job RFQ flow.
|
|
86
|
+
*
|
|
87
|
+
* Shape mirrors viem's `signTypedData` argument. Do not include the
|
|
88
|
+
* EIP712Domain entry in `types` — the parent injects it from `domain`.
|
|
89
|
+
*/
|
|
90
|
+
signTypedData(args: {
|
|
91
|
+
domain: SignTypedDataRequest['domain'];
|
|
92
|
+
types: SignTypedDataRequest['types'];
|
|
93
|
+
primaryType: string;
|
|
94
|
+
message: Readonly<Record<string, unknown>>;
|
|
95
|
+
}): Promise<Hex>;
|
|
96
|
+
/**
|
|
97
|
+
* Invoke a blueprint job. Returns a Promise that resolves on terminal
|
|
98
|
+
* status (`success` or `error`); subscribe to the `job` event for
|
|
99
|
+
* intermediate streaming chunks.
|
|
100
|
+
*
|
|
101
|
+
* Streaming opt-in: pass `stream: true` if the publisher's job emits
|
|
102
|
+
* chunks (LLM generation, video encoding). One-shot jobs (embeddings,
|
|
103
|
+
* classifications) skip the streaming machinery.
|
|
104
|
+
*/
|
|
105
|
+
callJob(args: {
|
|
106
|
+
jobIndex: number;
|
|
107
|
+
inputs: JobInputs;
|
|
108
|
+
stream?: boolean;
|
|
109
|
+
}): Promise<JobInvocation>;
|
|
110
|
+
private postHandshake;
|
|
111
|
+
private postToParent;
|
|
112
|
+
private handleParentMessage;
|
|
113
|
+
private dispatchWallet;
|
|
114
|
+
private handleJobResult;
|
|
115
|
+
private updateWallet;
|
|
116
|
+
private updateService;
|
|
117
|
+
private emit;
|
|
118
|
+
private ensureBootstrapped;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export { type ClientEventMap as C, type JobInvocation as J, type ServiceSnapshot as S, TangleIframeClient as T, type WalletSnapshot as W, type TangleIframeClientOptions as a };
|
package/dist/wallet/index.d.ts
CHANGED
|
@@ -1,30 +1,7 @@
|
|
|
1
|
+
export { T as TANGLE_CLOUD_ORIGINS_DEFAULT, d as detectTangleCloudParentOrigin } from '../detectParentOrigin-BYruoIdc.js';
|
|
1
2
|
import * as wagmi from 'wagmi';
|
|
2
|
-
import { Address
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Default Tangle Cloud origins. Consumers (agent-sandbox UI,
|
|
6
|
-
* trading-arena, future iframe blueprints) pass app-specific additions
|
|
7
|
-
* via `extraOrigins` rather than mutating this list.
|
|
8
|
-
*/
|
|
9
|
-
declare const TANGLE_CLOUD_ORIGINS_DEFAULT: readonly ["https://cloud.tangle.tools", "https://develop.cloud.tangle.tools", "http://localhost:4300", "http://localhost:8888"];
|
|
10
|
-
/**
|
|
11
|
-
* Returns the parent origin to bridge to, or null when no trusted parent is
|
|
12
|
-
* detected. Caller should skip installing the bridge connector when this
|
|
13
|
-
* returns null.
|
|
14
|
-
*
|
|
15
|
-
* `extraOrigins` is the application's escape hatch for staging or dev
|
|
16
|
-
* deploys not covered by the default list. The library deliberately does
|
|
17
|
-
* not read environment variables itself (consumers may bundle for non-Vite
|
|
18
|
-
* runtimes); the consuming app threads `import.meta.env.VITE_*` or
|
|
19
|
-
* `process.env.*` in itself.
|
|
20
|
-
*
|
|
21
|
-
* Falls back to a `?parent=<origin>` query parameter when no referrer is
|
|
22
|
-
* present (some browsers strip referrer from cross-origin loads). Useful
|
|
23
|
-
* for dev embedding flows.
|
|
24
|
-
*/
|
|
25
|
-
declare function detectTangleCloudParentOrigin(options?: {
|
|
26
|
-
extraOrigins?: readonly string[];
|
|
27
|
-
}): string | null;
|
|
3
|
+
import { Address } from 'viem';
|
|
4
|
+
export { A as AccountChanged, C as CallJobRequest, a as ChainChanged, b as ChainContext, H as HandshakeAck, c as HandshakeRequest, I as IframeRequest, J as JobInputs, d as JobResultEvent, e as JobResultStatus, N as NO_WALLET_ADDRESS, P as ParentMessage, R as ReadAccountRequest, f as ReadAccountResult, S as ServiceContextBroadcast, g as ServiceContextJob, h as ServiceContextOperator, i as SignMessageRequest, j as SignMessageResult, k as SignTransactionRequest, l as SignTransactionResult, m as SignTypedDataRequest, n as SignTypedDataResult, o as SwitchChainRequest, p as SwitchChainResult, T as TANGLE_IFRAME_PROTOCOL_PREFIX, q as TANGLE_IFRAME_PROTOCOL_VERSION, r as makeCorrelationId } from '../parentBridgeProtocol-BS2zbIvX.js';
|
|
28
5
|
|
|
29
6
|
type EventName = 'accountsChanged' | 'chainChanged' | 'connect' | 'disconnect' | 'message';
|
|
30
7
|
type Listener = (...args: unknown[]) => void;
|
|
@@ -89,6 +66,12 @@ declare class ParentBridgeProvider {
|
|
|
89
66
|
private requestSignTransaction;
|
|
90
67
|
private requestSwitchChain;
|
|
91
68
|
private dispatch;
|
|
69
|
+
/**
|
|
70
|
+
* Resolves wallet-shape responses (`{ ok, data | error }`). Job results
|
|
71
|
+
* use a different envelope (`{ status, data?, chunk?, error? }`) and are
|
|
72
|
+
* routed through a separate listener registered by `useCallJob` / the SDK
|
|
73
|
+
* — the provider doesn't double-handle them.
|
|
74
|
+
*/
|
|
92
75
|
private resolvePending;
|
|
93
76
|
private ensureBootstrapped;
|
|
94
77
|
private updateAccount;
|
|
@@ -103,86 +86,4 @@ declare class ParentBridgeProvider {
|
|
|
103
86
|
type ParentBridgeConnectorOptions = ParentBridgeOptions;
|
|
104
87
|
declare function parentBridgeConnector(options: ParentBridgeConnectorOptions): wagmi.CreateConnectorFn<ParentBridgeProvider, Record<string, unknown>, Record<string, unknown>>;
|
|
105
88
|
|
|
106
|
-
|
|
107
|
-
declare const TANGLE_IFRAME_PROTOCOL_PREFIX = "tangle.app.";
|
|
108
|
-
type HandshakeRequest = {
|
|
109
|
-
kind: 'tangle.app.handshake';
|
|
110
|
-
appId: string;
|
|
111
|
-
version: typeof TANGLE_IFRAME_PROTOCOL_VERSION;
|
|
112
|
-
};
|
|
113
|
-
type ReadAccountRequest = {
|
|
114
|
-
kind: 'tangle.app.readAccount';
|
|
115
|
-
correlationId: string;
|
|
116
|
-
};
|
|
117
|
-
type SwitchChainRequest = {
|
|
118
|
-
kind: 'tangle.app.switchChain';
|
|
119
|
-
correlationId: string;
|
|
120
|
-
chainId: number;
|
|
121
|
-
};
|
|
122
|
-
type SignMessageRequest = {
|
|
123
|
-
kind: 'tangle.app.signMessage';
|
|
124
|
-
correlationId: string;
|
|
125
|
-
chainId: number;
|
|
126
|
-
message: string;
|
|
127
|
-
};
|
|
128
|
-
type SignTransactionRequest = {
|
|
129
|
-
kind: 'tangle.app.signTransaction';
|
|
130
|
-
correlationId: string;
|
|
131
|
-
chainId: number;
|
|
132
|
-
to: Address;
|
|
133
|
-
data: Hex;
|
|
134
|
-
value?: string;
|
|
135
|
-
};
|
|
136
|
-
type HandshakeAck = {
|
|
137
|
-
kind: 'tangle.app.handshakeAck';
|
|
138
|
-
appId: string;
|
|
139
|
-
protocolVersion: typeof TANGLE_IFRAME_PROTOCOL_VERSION;
|
|
140
|
-
};
|
|
141
|
-
type ResultEnvelope<T> = {
|
|
142
|
-
correlationId: string;
|
|
143
|
-
} & ({
|
|
144
|
-
ok: true;
|
|
145
|
-
data: T;
|
|
146
|
-
} | {
|
|
147
|
-
ok: false;
|
|
148
|
-
error: string;
|
|
149
|
-
});
|
|
150
|
-
type ReadAccountResult = {
|
|
151
|
-
kind: 'tangle.app.readAccountResult';
|
|
152
|
-
} & ResultEnvelope<{
|
|
153
|
-
account: Address;
|
|
154
|
-
chainId: number;
|
|
155
|
-
}>;
|
|
156
|
-
type SwitchChainResult = {
|
|
157
|
-
kind: 'tangle.app.switchChainResult';
|
|
158
|
-
} & ResultEnvelope<{
|
|
159
|
-
chainId: number;
|
|
160
|
-
}>;
|
|
161
|
-
type SignMessageResult = {
|
|
162
|
-
kind: 'tangle.app.signMessageResult';
|
|
163
|
-
} & ResultEnvelope<{
|
|
164
|
-
signature: Hex;
|
|
165
|
-
}>;
|
|
166
|
-
type SignTransactionResult = {
|
|
167
|
-
kind: 'tangle.app.signTransactionResult';
|
|
168
|
-
} & ResultEnvelope<{
|
|
169
|
-
txHash: Hex;
|
|
170
|
-
}>;
|
|
171
|
-
type AccountChanged = {
|
|
172
|
-
kind: 'tangle.app.accountChanged';
|
|
173
|
-
account: Address | null;
|
|
174
|
-
};
|
|
175
|
-
type ChainChanged = {
|
|
176
|
-
kind: 'tangle.app.chainChanged';
|
|
177
|
-
chainId: number;
|
|
178
|
-
};
|
|
179
|
-
type ParentMessage = HandshakeAck | ReadAccountResult | SwitchChainResult | SignMessageResult | SignTransactionResult | AccountChanged | ChainChanged;
|
|
180
|
-
declare const NO_WALLET_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
181
|
-
/**
|
|
182
|
-
* Cryptographically-random ASCII correlation id matching the parent's
|
|
183
|
-
* validator regex (`/^[\w.\-:]+$/`, max length 128). The connector keeps a
|
|
184
|
-
* Map<correlationId, Resolver> so each request resolves independently.
|
|
185
|
-
*/
|
|
186
|
-
declare function makeCorrelationId(prefix: string): string;
|
|
187
|
-
|
|
188
|
-
export { type AccountChanged, type ChainChanged, type HandshakeAck, type HandshakeRequest, NO_WALLET_ADDRESS, type ParentBridgeConnectorOptions, type ParentBridgeOptions, ParentBridgeProvider, type ParentMessage, type ReadAccountRequest, type ReadAccountResult, type SignMessageRequest, type SignMessageResult, type SignTransactionRequest, type SignTransactionResult, type SwitchChainRequest, type SwitchChainResult, TANGLE_CLOUD_ORIGINS_DEFAULT, TANGLE_IFRAME_PROTOCOL_PREFIX, TANGLE_IFRAME_PROTOCOL_VERSION, detectTangleCloudParentOrigin, isRunningInIframe, makeCorrelationId, parentBridgeConnector };
|
|
89
|
+
export { type ParentBridgeConnectorOptions, type ParentBridgeOptions, ParentBridgeProvider, isRunningInIframe, parentBridgeConnector };
|
package/dist/wallet/index.js
CHANGED
|
@@ -1,54 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
function originFromReferrer() {
|
|
10
|
-
if (typeof document === "undefined") return null;
|
|
11
|
-
const ref = document.referrer;
|
|
12
|
-
if (!ref) return null;
|
|
13
|
-
try {
|
|
14
|
-
return new URL(ref).origin;
|
|
15
|
-
} catch {
|
|
16
|
-
return null;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
function detectTangleCloudParentOrigin(options = {}) {
|
|
20
|
-
if (typeof window === "undefined" || window.parent === window) {
|
|
21
|
-
return null;
|
|
22
|
-
}
|
|
23
|
-
const allowlist = /* @__PURE__ */ new Set([
|
|
24
|
-
...TANGLE_CLOUD_ORIGINS_DEFAULT,
|
|
25
|
-
...options.extraOrigins ?? []
|
|
26
|
-
]);
|
|
27
|
-
const referrerOrigin = originFromReferrer();
|
|
28
|
-
if (referrerOrigin && allowlist.has(referrerOrigin)) {
|
|
29
|
-
return referrerOrigin;
|
|
30
|
-
}
|
|
31
|
-
try {
|
|
32
|
-
const url = new URL(window.location.href);
|
|
33
|
-
const explicit = url.searchParams.get("parent");
|
|
34
|
-
if (explicit && allowlist.has(explicit)) return explicit;
|
|
35
|
-
} catch {
|
|
36
|
-
}
|
|
37
|
-
return null;
|
|
38
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
NO_WALLET_ADDRESS,
|
|
3
|
+
TANGLE_CLOUD_ORIGINS_DEFAULT,
|
|
4
|
+
TANGLE_IFRAME_PROTOCOL_PREFIX,
|
|
5
|
+
TANGLE_IFRAME_PROTOCOL_VERSION,
|
|
6
|
+
detectTangleCloudParentOrigin,
|
|
7
|
+
makeCorrelationId
|
|
8
|
+
} from "../chunk-ZKICSKZH.js";
|
|
39
9
|
|
|
40
10
|
// src/wallet/parentBridgeConnector.ts
|
|
41
11
|
import { createConnector } from "wagmi";
|
|
42
12
|
|
|
43
|
-
// src/wallet/parentBridgeProtocol.ts
|
|
44
|
-
var TANGLE_IFRAME_PROTOCOL_VERSION = "1";
|
|
45
|
-
var TANGLE_IFRAME_PROTOCOL_PREFIX = "tangle.app.";
|
|
46
|
-
var NO_WALLET_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
47
|
-
function makeCorrelationId(prefix) {
|
|
48
|
-
const random = typeof crypto !== "undefined" && typeof crypto.randomUUID === "function" ? crypto.randomUUID() : Math.random().toString(36).slice(2) + Date.now().toString(36);
|
|
49
|
-
return `${prefix}.${random}`;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
13
|
// src/wallet/parentBridgeProvider.ts
|
|
53
14
|
var DEFAULT_REQUEST_TIMEOUT_MS = 6e4;
|
|
54
15
|
function isRunningInIframe() {
|
|
@@ -260,6 +221,12 @@ var ParentBridgeProvider = class {
|
|
|
260
221
|
});
|
|
261
222
|
});
|
|
262
223
|
}
|
|
224
|
+
/**
|
|
225
|
+
* Resolves wallet-shape responses (`{ ok, data | error }`). Job results
|
|
226
|
+
* use a different envelope (`{ status, data?, chunk?, error? }`) and are
|
|
227
|
+
* routed through a separate listener registered by `useCallJob` / the SDK
|
|
228
|
+
* — the provider doesn't double-handle them.
|
|
229
|
+
*/
|
|
263
230
|
resolvePending(message) {
|
|
264
231
|
const entry = this.pending.get(message.correlationId);
|
|
265
232
|
if (!entry) return;
|