@human.tech/waap-sdk 2.2.0 → 2.4.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/CHANGELOG.md +120 -0
- package/dist/SolanaProvider-CxJX9Dzo.js +1 -0
- package/dist/SolanaProvider-CygEwKg1.mjs +1 -0
- package/dist/WaaPError-BuwfZjBk.d.mts +52 -0
- package/dist/WaaPError-BuwfZjBk.d.ts +52 -0
- package/dist/{WaaPError-D64X-oFe.d.ts → WalletModalController-Qh9LNwW5.d.ts} +17 -48
- package/dist/{WaaPError-QHdMfZW7.d.mts → WalletModalController-wIHBGOVd.d.mts} +17 -48
- package/dist/bridge.d.mts +158 -0
- package/dist/bridge.d.ts +158 -0
- package/dist/bridge.js +1 -0
- package/dist/bridge.mjs +1 -0
- package/dist/evm-64xq-c4L.js +2 -0
- package/dist/evm-ChOfSh-X.mjs +2 -0
- package/dist/evm.d.mts +3 -2
- package/dist/evm.d.ts +3 -2
- package/dist/evm.js +1 -1
- package/dist/evm.mjs +1 -1
- package/dist/{index-DOIss_GK.d.ts → index-DNyKwJcJ.d.ts} +3 -184
- package/dist/{index-C0mLQs_a.d.mts → index-XdQjHMzI.d.mts} +3 -184
- package/dist/index.d.mts +30 -11
- package/dist/index.d.ts +30 -11
- package/dist/index.js +2 -2
- package/dist/index.mjs +2 -2
- package/dist/{initializerContext-_YjbVTiL.d.mts → initializerContext-DB5E2A6s.d.mts} +1 -1
- package/dist/{initializerContext-DIrqEE6B.d.ts → initializerContext-Z7JeZRsm.d.ts} +1 -1
- package/dist/react.d.mts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +1 -1
- package/dist/react.mjs +1 -1
- package/dist/register-BAygaKgr.mjs +1 -0
- package/dist/{register-9bEe9ATz.d.mts → register-BhybMFR2.d.mts} +3 -3
- package/dist/{register-PWKDsSRv.d.ts → register-CMv6n7ak.d.ts} +3 -3
- package/dist/register-CdSpQr2m.js +1 -0
- package/dist/register-CoFt8w20.mjs +1 -0
- package/dist/register-DEFLr1aE.js +1 -0
- package/dist/{register-Mb1D_xW4.d.ts → register-DfUAOQke.d.mts} +3 -3
- package/dist/{register-XzDVa7r8.d.mts → register-MK9ivXiJ.d.ts} +3 -3
- package/dist/solana.d.mts +6 -4
- package/dist/solana.d.ts +6 -4
- package/dist/solana.js +1 -1
- package/dist/solana.mjs +1 -1
- package/dist/sui.d.mts +5 -4
- package/dist/sui.d.ts +5 -4
- package/dist/sui.js +1 -1
- package/dist/sui.mjs +1 -1
- package/dist/types-8CCmbLuY.d.ts +191 -0
- package/dist/types-Bfz205sD.d.mts +191 -0
- package/dist/{types-BmCqyQtu.d.mts → types-x7TOncUp.d.mts} +13 -1
- package/dist/{types-BmCqyQtu.d.ts → types-x7TOncUp.d.ts} +13 -1
- package/dist/ui-Bd49qoIs.js +1 -0
- package/dist/ui-CI7vln8d.mjs +1 -0
- package/dist/useWaapAuth-C9Cwu4XG.js +1 -0
- package/dist/{useWaapAuth-vJAk2n_I.d.mts → useWaapAuth-CMhYoBKA.d.mts} +2 -2
- package/dist/{useWaapAuth-DgYO5KxO.d.ts → useWaapAuth-CeJuu2wk.d.ts} +2 -2
- package/dist/useWaapAuth-Vh8gUs6Y.mjs +1 -0
- package/package.json +24 -3
- package/dist/esm-BUfmyWbN.mjs +0 -1
- package/dist/esm-DFwVZkjo.js +0 -1
- package/dist/evm-BINU4e1N.mjs +0 -2
- package/dist/evm-BXkH-I90.js +0 -2
- package/dist/register-CdhMOOIi.mjs +0 -1
- package/dist/register-DEhrbVMU.js +0 -1
- package/dist/register-DfLqs9vQ.mjs +0 -1
- package/dist/register-jgVHbdqY.js +0 -1
- package/dist/ui-9HR3zyVP.mjs +0 -1
- package/dist/ui-BHIqqJWQ.js +0 -1
- package/dist/useWaapAuth-BPvve-_3.js +0 -1
- package/dist/useWaapAuth-BcmVGb-D.mjs +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,125 @@
|
|
|
1
1
|
# @human.tech/waap-sdk
|
|
2
2
|
|
|
3
|
+
## 2.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 6240f2e: Add `build:bridge-page`, which generates the immutable HTML page a native
|
|
8
|
+
WebView loads to drive the SDK.
|
|
9
|
+
|
|
10
|
+
The page bundles the real `@human.tech/waap-sdk/bridge` entry, so the Flutter
|
|
11
|
+
package vendors no hand-written JavaScript and the two cannot drift.
|
|
12
|
+
|
|
13
|
+
WalletConnect/AppKit is stubbed out of that bundle. It is not a V1 native login
|
|
14
|
+
method and is reached only through `await import('@reown/…')` inside
|
|
15
|
+
`SilkWalletConnect.getInstance()`, but an IIFE bundle cannot code-split, so
|
|
16
|
+
leaving it in inlines the entire AppKit graph — viem, ox, the Coinbase and Base
|
|
17
|
+
SDKs, an icon set. That is the difference between a 140 kB page and a 4.3 MB
|
|
18
|
+
one parsed on a phone at every launch. The stub throws a legible error rather
|
|
19
|
+
than failing as an opaque module-resolution error, so the excluded path stays
|
|
20
|
+
loud.
|
|
21
|
+
|
|
22
|
+
`esbuild` becomes an explicit devDependency; it was previously only reachable
|
|
23
|
+
as a transitive dependency of `tsdown`.
|
|
24
|
+
|
|
25
|
+
- a87adeb: Add `@human.tech/waap-sdk/bridge`, the shared runtime a native application's
|
|
26
|
+
WebView bridge page uses to drive the browser SDK.
|
|
27
|
+
|
|
28
|
+
This is the JavaScript half of the Flutter SDK's architecture, and it is
|
|
29
|
+
deliberately host-agnostic: the same bridge serves any native layer that can
|
|
30
|
+
install a message channel on a WebView.
|
|
31
|
+
|
|
32
|
+
The bridge page is a distinct origin from the wallet. The wallet stays in a
|
|
33
|
+
cross-origin iframe that application JavaScript cannot reach, so the native host
|
|
34
|
+
talks only to this module and never to wallet DOM, storage or credentials.
|
|
35
|
+
|
|
36
|
+
**A versioned envelope that fails closed.** Unknown protocol versions, message
|
|
37
|
+
kinds the host must never send (a `response` or `event` among them), missing or
|
|
38
|
+
non-string ids, unknown bridge methods and malformed JSON are all refused before
|
|
39
|
+
anything reaches the SDK. A failure is reported against the caller's id whenever
|
|
40
|
+
one can be recovered, so a native future rejects rather than hanging; only a
|
|
41
|
+
message with no usable id degrades to an out-of-band event.
|
|
42
|
+
|
|
43
|
+
**Exactly-once settlement.** A settled request id is retired, so a late resolve
|
|
44
|
+
or a second rejection cannot reach the host twice, and a second request reusing
|
|
45
|
+
an in-flight id is refused rather than silently replacing it.
|
|
46
|
+
|
|
47
|
+
**`evm.request` is allowlisted, and the allowlist is load-bearing.**
|
|
48
|
+
`SILK_METHOD` mixes the EIP-1193 methods with portal-admin and configuration
|
|
49
|
+
methods — `project_init`, `gastank_topup`, `gastank_update_settings`,
|
|
50
|
+
`customization_update`, `set_project`, `set_custom_config`. Forwarding the
|
|
51
|
+
escape hatch unfiltered would hand a native application a path to all of them.
|
|
52
|
+
The allowed set is enumerated rather than derived from an `eth_`/`wallet_`
|
|
53
|
+
prefix, so extending the enum cannot silently widen the native surface.
|
|
54
|
+
|
|
55
|
+
**Errors cross redacted.** Only a stable native error code, a message and any
|
|
56
|
+
EIP-1193 number are sent; the originating cause is dropped because it can carry
|
|
57
|
+
request payloads and wallet internals. The code map is exhaustive over
|
|
58
|
+
`WaaPErrorCode`, so adding an SDK code fails type-checking here rather than
|
|
59
|
+
degrading to `unknown` on a user's device.
|
|
60
|
+
|
|
61
|
+
33 tests cover the protocol rules, the allowlist against every method it admits
|
|
62
|
+
and every portal-admin method it must refuse, redaction, teardown and event
|
|
63
|
+
forwarding.
|
|
64
|
+
|
|
65
|
+
### Patch Changes
|
|
66
|
+
|
|
67
|
+
- 306ec08: Add `homepage` (docs) and `keywords` to package.json so the npm sidebar links to docs.waap.human.tech instead of the private silk repo.
|
|
68
|
+
- ef2f368: Release the Squid onboarding latch when the wallet stops reporting progress.
|
|
69
|
+
|
|
70
|
+
`onboard()` opens with `if (isSquidReady() || activeLifecycleId) return`, and
|
|
71
|
+
`activeLifecycleId` was only ever cleared by a `waap_squid_failed` event, a
|
|
72
|
+
throw inside `onboard()`, a successful `getAccountStatus()` reconcile, or
|
|
73
|
+
`logout()`. None of those fire when an attempt simply goes silent, so an
|
|
74
|
+
integrator whose onboarding died without a terminal event was stuck:
|
|
75
|
+
`getSquidStatus()` reported `provisioning` forever, and every later `onboard()`
|
|
76
|
+
returned immediately without reaching the wallet.
|
|
77
|
+
|
|
78
|
+
An attempt that emits nothing for three minutes is now treated as failed and
|
|
79
|
+
emits `waap_squid_failed`, which updates status and frees a retry. This bounds silence rather
|
|
80
|
+
than slowness — the wallet re-posts `pending` on every network-DKG poll, so a
|
|
81
|
+
legitimately slow provision keeps resetting the timer and is never cut off.
|
|
82
|
+
|
|
83
|
+
No API change: the recovery is a plain `onboard()` call.
|
|
84
|
+
|
|
85
|
+
Bound the shared native sign-ticket request to 45 seconds. A stalled ticket
|
|
86
|
+
request previously prevented SDK and CLI Squid onboarding from reaching DKG or
|
|
87
|
+
reporting a failure.
|
|
88
|
+
|
|
89
|
+
Keep CLI TAP registration recovery within the preparation phase and inspect the
|
|
90
|
+
underlying failure, so an operation ID containing `403` cannot cause a failed
|
|
91
|
+
transaction to be replayed.
|
|
92
|
+
|
|
93
|
+
## 2.3.0
|
|
94
|
+
|
|
95
|
+
### Minor Changes
|
|
96
|
+
|
|
97
|
+
- 96185f8: Surface a refused gas-tank charge to integrating dapps.
|
|
98
|
+
|
|
99
|
+
Squid signing is now billed against the user's WaaP gas tank, and a signature
|
|
100
|
+
whose fee cannot be covered is refused with HTTP 402 before the signature
|
|
101
|
+
happens. Previously that reached a dapp as a generic wallet failure — the
|
|
102
|
+
category a dapp retries, which is exactly wrong for an outcome only the user
|
|
103
|
+
can resolve and that retrying cannot change.
|
|
104
|
+
|
|
105
|
+
Two additions:
|
|
106
|
+
|
|
107
|
+
- `WaaPErrorCode` gains `insufficient_balance`, and `normalizeWaaPError`
|
|
108
|
+
classifies the refusal into it. A gas tank the wallet could not _reach_
|
|
109
|
+
still classifies as `wallet_error`, so the retryable case keeps its meaning
|
|
110
|
+
— mirroring the split the server draws between its 402 and its 502.
|
|
111
|
+
- Errors from the EIP-1193 provider carry a `waapCode` property alongside
|
|
112
|
+
whatever the wallet threw. The thrown value is deliberately **not** replaced:
|
|
113
|
+
wagmi and viem detect a user rejection by `code === 4001`, and normalising
|
|
114
|
+
into a `WaaPError` (whose `code` is a string) would take that away from every
|
|
115
|
+
existing integration. `waapCode` rides alongside instead, which is what makes
|
|
116
|
+
`insufficient_balance` reachable from the provider path at all — no EIP-1193
|
|
117
|
+
code expresses it.
|
|
118
|
+
|
|
119
|
+
Note for consumers doing an exhaustive `switch` over `WaaPErrorCode`: widening
|
|
120
|
+
the union is a compile error for that pattern. Comparisons against individual
|
|
121
|
+
codes are unaffected.
|
|
122
|
+
|
|
3
123
|
## 2.2.0
|
|
4
124
|
|
|
5
125
|
### Minor Changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e=require("./evm-64xq-c4L.js");let t=require("events");var n=class{constructor(n,r={},i,a=r){this.lastKnownConversion=`pending`,this.name=`WaaP`,this.version=`1.0.0`,this.icon=`data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NCA2NCI+PHJlY3Qgd2lkdGg9IjY0IiBoZWlnaHQ9IjY0IiByeD0iMTYiIGZpbGw9IiMxMTE4MmMiLz48cGF0aCBkPSJNMTYgNDhoMzJMMzIgMTZ6IiBmaWxsPSIjN2NkNGZmIi8+PC9zdmc+`,this._accounts=[],this.accountMode=`tap`,this.loginMethod=null,this._chains=[`solana:mainnet`,`solana:devnet`,`solana:testnet`],this.internalEventEmitter=new t.EventEmitter,this.changeListeners=new Set,this.initializerPromise=null,this.initializedIframeWindow=null,this.walletMessageManager=new e.h(n,e.S(r)),this.ensureIframe=i,this.iframeMounted=!i,this.initializerOptions=a,this.uiMessageManager=new e.a,this.walletMessageManager.addListener({handleResponse:e=>{this.internalEventEmitter.emit(e.id,e)},handleRequest:t=>{t.method===e.O.show_modal?this.uiMessageManager.emit(`show_modal`):t.method===e.O.hide_modal&&this.uiMessageManager.emit(`hide_modal`)},onAccountChanged:async()=>{try{let e=await this.refreshAccounts();this.notifyChange({accounts:e.accounts})}catch(e){console.error(`Failed to refresh Solana accounts:`,e),this._accounts=[],this.notifyChange({accounts:[]})}}})}destroy(){this.walletMessageManager.dispose(),this.internalEventEmitter.removeAllListeners(),this.uiMessageManager.removeAllListeners(),this.changeListeners.clear(),this._accounts=[]}ensureIframeMounted(){if(this.iframeMounted||!this.ensureIframe)return;let e=this.ensureIframe();if(!e)throw Error(`Failed to create WaaP iframe`);this.iframeMounted=!0,this.walletMessageManager.setIframeWindow(e)}async preload(){if(!this.ensureIframe)return;this.ensureIframeMounted();let t=this.walletMessageManager.getIframeWindow();if(!t)throw Error(`WaaP iframe is not mounted`);if(this.initializedIframeWindow===t&&this.initializerPromise)return this.initializerPromise;this.initializedIframeWindow=t,this.initializerPromise=e.v(t,()=>this.selectAccountMode(this.accountMode,this.initializerOptions));try{await this.initializerPromise}catch(e){throw this.initializerPromise=null,this.initializedIframeWindow=null,e}}async ensureInitialized(){await this.preload()}get chains(){return this._chains}get accounts(){return this._accounts}get features(){return{"standard:connect":{version:`1.0.0`,connect:this.connect.bind(this)},"standard:disconnect":{version:`1.0.0`,disconnect:this.disconnect.bind(this)},"standard:events":{version:`1.0.0`,on:this.on.bind(this)},"solana:signMessage":{version:`1.1.0`,signMessage:this.signStandardMessages.bind(this)},"solana:signTransaction":{version:`1.0.0`,supportedTransactionVersions:[`legacy`,0],signTransaction:this.signStandardTransactions.bind(this)},"solana:signAndSendTransaction":{version:`1.0.0`,supportedTransactionVersions:[`legacy`,0],signAndSendTransaction:this.signAndSendStandardTransactions.bind(this)}}}get ui(){return this.uiMessageManager}getAccountStatus(){return{authenticated:this.loginMethod!==null,loginMethod:this.loginMethod,activeMode:this.loginMethod?this.accountMode:null,mode:this.accountMode,conversion:this.loginMethod?this.lastKnownConversion:`not_required`,tap:null,squid:null,accounts:this._accounts[0]?{solana:this._accounts[0].address}:{}}}get session(){return{login:()=>this.login(),logout:()=>this.logout(),getLoginMethod:()=>this.getLoginMethod(),getAccountStatus:()=>this.getCanonicalAccountStatus()}}async getCanonicalAccountStatus(){await this.ensureInitialized();let t=await this.postRequestAndWait({method:e.O.waap_getAccountStatus,params:[],interactionRequired:!1});if(t.error)throw Error(t.error.message||`Failed to read WaaP status`);let n=t.data;return this.syncLoginMethodFromCanonicalStatus(n),n?.conversion&&(this.lastKnownConversion=n.conversion),n}setAccountMode(e){this.accountMode=e,this.initializerPromise=null,this.initializedIframeWindow=null}async selectAccountMode(t,n={}){await this.walletMessageManager.pingIframe(),await this.postRequestAndWait({method:e.O.set_signing_mode,params:[e.g(t,n)],interactionRequired:!1})}setLoginMethod(e){this.loginMethod=e,e===null&&(this._accounts=[],this.notifyChange({accounts:[]}))}getLoginMethod(){return this.loginMethod}async login(){await this.ensureInitialized();let t=await this.restoreSession();if(t)return t;let n=(await this.postRequestAndWait({method:e.O.login,params:[],interactionRequired:!0})).data;return n!==`waap`&&n!==`human`&&n!==`injected`&&n!==`walletconnect`?(this.loginMethod=null,null):(this.loginMethod=n,n)}async logout(){this.lastKnownConversion=`pending`,await this.ensureInitialized(),await this.postRequestAndWait({method:e.O.logout,params:[],interactionRequired:!1}),this.loginMethod=null,this._accounts=[],this.notifyChange({accounts:[]})}async refreshAccounts(){try{await this.ensureInitialized();let e=await this.postRequestAndWait({method:`solana_connect`,params:[{silent:!0}],interactionRequired:!1});if(e.error)return this._accounts=[],{accounts:[]};let t=this.normalizeAccounts(e.data?.accounts||[]);return this._accounts=t,{accounts:this._accounts}}catch{return this._accounts=[],{accounts:[]}}}normalizeAccounts(e){return e.map(e=>({address:e.address,publicKey:e.publicKey instanceof Uint8Array?e.publicKey:new Uint8Array(e.publicKey??[]),chains:e.chains??this._chains,features:e.features??[]}))}async connect(t){if(!this.loginMethod)throw new e.T(`not_authenticated`,`Not authenticated: call login() before connect().`,{operation:{chain:`solana`,method:`solana_connect`}});await this.ensureInitialized();let n=await this.postRequestAndWait({method:`solana_connect`,params:[t||{}],interactionRequired:!t?.silent,signal:t?.signal,timeoutMs:t?.timeoutMs});if(n.error)throw Error(n.error.message||`Failed to connect`);let r=this.normalizeAccounts(n.data?.accounts||[]);return this._accounts=r,this.notifyChange({accounts:this._accounts}),t?.silent||this.internalEventEmitter.emit(`connect`),this.internalEventEmitter.emit(`accountsChanged`,this._accounts.map(e=>e.address)),{accounts:this._accounts}}async restoreSession(){try{let e=await this.getCanonicalAccountStatus();if(e.authenticated&&(e.loginMethod===`waap`||e.loginMethod===`human`||e.loginMethod===`injected`||e.loginMethod===`walletconnect`))return this.loginMethod=e.loginMethod,e.loginMethod}catch{}return null}syncLoginMethodFromCanonicalStatus(e){let t=e.authenticated&&(e.loginMethod===`waap`||e.loginMethod===`human`||e.loginMethod===`injected`||e.loginMethod===`walletconnect`)?e.loginMethod:null;t!==this.loginMethod&&this.setLoginMethod(t)}async disconnect(){await this.ensureInitialized(),await this.postRequestAndWait({method:`solana_disconnect`,params:[],interactionRequired:!1}),this._accounts=[],this.notifyChange({accounts:[]})}async signMessage(e){await this.ensureInitialized();let t=e.account.address;if(!this._accounts.some(e=>e.address===t))throw Error(`Account ${t} is not connected`);let n=await this.postRequestAndWait({method:`solana_signMessage`,params:[{message:Array.from(e.message),account:t}],interactionRequired:!0,signal:e.signal,timeoutMs:e.timeoutMs});if(n.error)throw Error(n.error.message||`Failed to sign message`);return{signedMessage:new Uint8Array(n.data.signedMessage),signature:new Uint8Array(n.data.signature)}}async signTransaction(e){await this.ensureInitialized();let t=e.account.address;if(!this._accounts.some(e=>e.address===t))throw Error(`Account ${t} is not connected`);let n=this.resolveTransactionBytes(e.transaction),r=await this.postRequestAndWait({method:`solana_signTransaction`,params:[{transaction:Array.from(n),account:t,chain:e.chain,withPT:e.withPT}],interactionRequired:!0,signal:e.signal,timeoutMs:e.timeoutMs});if(r.error)throw Error(r.error.message||`Failed to sign transaction`);return{signedTransaction:new Uint8Array(r.data.signedTransaction),signature:new Uint8Array(r.data.signature)}}async signAndSendTransaction(e){await this.ensureInitialized();let t=e.account.address;if(!this._accounts.some(e=>e.address===t))throw Error(`Account ${t} is not connected`);let n=this.resolveTransactionBytes(e.transaction),r=await this.postRequestAndWait({method:`solana_signAndSendTransaction`,params:[{transaction:Array.from(n),account:t,chain:e.chain,options:e.options,withPT:e.withPT}],interactionRequired:!0,signal:e.signal,timeoutMs:e.timeoutMs});if(r.error)throw Error(r.error.message||`Failed to sign and send transaction`);return{signature:r.data.signature}}async signStandardMessages(...e){let t=[];for(let n of e){let e=await this.signMessage({account:n.account,message:n.message});t.push({...e,signatureType:`ed25519`})}return t}async signStandardTransactions(...e){let t=[];for(let n of e){let e=await this.signTransaction({account:n.account,transaction:n.transaction,chain:this.asSupportedChain(n.chain)});t.push({signedTransaction:e.signedTransaction})}return t}async signAndSendStandardTransactions(...e){let t=[];for(let n of e){let e=await this.signAndSendTransaction({account:n.account,transaction:n.transaction,chain:this.asSupportedChain(n.chain),options:this.broadcastOptions(n.options)});t.push({signature:r(e.signature)})}return t}asSupportedChain(t){if(t!==void 0){if(this._chains.includes(t))return t;throw new e.T(`unsupported_input`,`Unsupported Solana Wallet Standard chain: ${t}`,{operation:{chain:`solana`,method:`wallet_standard`}})}}broadcastOptions(t){if(t?.preflightCommitment!==void 0||t?.minContextSlot!==void 0||t?.commitment!==void 0)throw new e.T(`unsupported_input`,`WaaP does not support Wallet Standard RPC commitment options; configure the dapp RPC instead.`,{operation:{chain:`solana`,method:`wallet_standard`}});return t?{skipPreflight:t.skipPreflight,maxRetries:t.maxRetries}:void 0}async requestPermissionToken(t){await this.ensureInitialized();let n={...t,walletMode:this.accountMode},r=await this.postRequestAndWait({method:e.O.waap_requestPermissionToken,params:[n],interactionRequired:!0});if(r.error)throw Error(r.error.message||`Failed to request permission token`);return r.data}async getPermissionTokenStatus(t){return await this.ensureInitialized(),(await this.postRequestAndWait({method:e.O.waap_getPermissionTokenStatus,params:[t],interactionRequired:!1})).data}async clearPermissionToken(t){return await this.ensureInitialized(),(await this.postRequestAndWait({method:e.O.waap_clearPermissionToken,params:[t],interactionRequired:!1})).data}resolveTransactionBytes(e){if(e instanceof Uint8Array)return e;if(Array.isArray(e))return new Uint8Array(e);if(e&&typeof e.serialize==`function`){let t=e.serialize();return t instanceof Uint8Array?t:new Uint8Array(t)}throw Error(`Unsupported transaction format. Pass serialized bytes or a @solana/web3.js Transaction.`)}on(e,t){return e===`change`?(this.changeListeners.add(t),()=>{this.changeListeners.delete(t)}):(this.internalEventEmitter.on(e,t),()=>{this.internalEventEmitter.removeListener(e,t)})}removeListener(e,t){if(e===`change`){this.changeListeners.delete(t);return}this.internalEventEmitter.removeListener(e,t)}async postRequestAndWait(t){let n;try{t.interactionRequired&&e.p({layout:t.method===e.O.login?`auth`:`signing`}),n=await this.walletMessageManager.postSilkRequest({method:t.method,params:t.params,interactionRequired:t.interactionRequired});let r=await e.u({eventEmitter:this.internalEventEmitter,id:n,method:t.method,interactionRequired:t.interactionRequired,signal:t.signal,timeoutMs:t.timeoutMs,onCancel:()=>{this.walletMessageManager.cancelSilkRequest(n,t.method),t.interactionRequired&&e.f()}});if(r.error)throw Error(r.error.message);return r}catch(r){throw t.interactionRequired&&n===void 0&&e.f(),e.E(r,{chain:`solana`,method:String(t.method),requestId:n})}}notifyChange(e){Array.from(this.changeListeners).forEach(t=>{t(e)})}};function r(e){let t=[];for(let n of e){let e=`123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz`.indexOf(n);if(e<0)throw Error(`Invalid base58 transaction signature`);for(let n=0;n<t.length;n+=1)e+=t[n]*58,t[n]=e&255,e>>=8;for(;e>0;)t.push(e&255),e>>=8}let n=0;for(;n<e.length&&e[n]===`1`;)n+=1;return new Uint8Array([...Array(n).fill(0),...t.reverse()])}Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return n}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{E as e,O as t,S as n,T as r,a as i,f as a,g as o,h as s,p as c,u as l,v as u}from"./evm-ChOfSh-X.mjs";import{EventEmitter as d}from"events";var f=class{constructor(e,r={},a,o=r){this.lastKnownConversion=`pending`,this.name=`WaaP`,this.version=`1.0.0`,this.icon=`data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NCA2NCI+PHJlY3Qgd2lkdGg9IjY0IiBoZWlnaHQ9IjY0IiByeD0iMTYiIGZpbGw9IiMxMTE4MmMiLz48cGF0aCBkPSJNMTYgNDhoMzJMMzIgMTZ6IiBmaWxsPSIjN2NkNGZmIi8+PC9zdmc+`,this._accounts=[],this.accountMode=`tap`,this.loginMethod=null,this._chains=[`solana:mainnet`,`solana:devnet`,`solana:testnet`],this.internalEventEmitter=new d,this.changeListeners=new Set,this.initializerPromise=null,this.initializedIframeWindow=null,this.walletMessageManager=new s(e,n(r)),this.ensureIframe=a,this.iframeMounted=!a,this.initializerOptions=o,this.uiMessageManager=new i,this.walletMessageManager.addListener({handleResponse:e=>{this.internalEventEmitter.emit(e.id,e)},handleRequest:e=>{e.method===t.show_modal?this.uiMessageManager.emit(`show_modal`):e.method===t.hide_modal&&this.uiMessageManager.emit(`hide_modal`)},onAccountChanged:async()=>{try{let e=await this.refreshAccounts();this.notifyChange({accounts:e.accounts})}catch(e){console.error(`Failed to refresh Solana accounts:`,e),this._accounts=[],this.notifyChange({accounts:[]})}}})}destroy(){this.walletMessageManager.dispose(),this.internalEventEmitter.removeAllListeners(),this.uiMessageManager.removeAllListeners(),this.changeListeners.clear(),this._accounts=[]}ensureIframeMounted(){if(this.iframeMounted||!this.ensureIframe)return;let e=this.ensureIframe();if(!e)throw Error(`Failed to create WaaP iframe`);this.iframeMounted=!0,this.walletMessageManager.setIframeWindow(e)}async preload(){if(!this.ensureIframe)return;this.ensureIframeMounted();let e=this.walletMessageManager.getIframeWindow();if(!e)throw Error(`WaaP iframe is not mounted`);if(this.initializedIframeWindow===e&&this.initializerPromise)return this.initializerPromise;this.initializedIframeWindow=e,this.initializerPromise=u(e,()=>this.selectAccountMode(this.accountMode,this.initializerOptions));try{await this.initializerPromise}catch(e){throw this.initializerPromise=null,this.initializedIframeWindow=null,e}}async ensureInitialized(){await this.preload()}get chains(){return this._chains}get accounts(){return this._accounts}get features(){return{"standard:connect":{version:`1.0.0`,connect:this.connect.bind(this)},"standard:disconnect":{version:`1.0.0`,disconnect:this.disconnect.bind(this)},"standard:events":{version:`1.0.0`,on:this.on.bind(this)},"solana:signMessage":{version:`1.1.0`,signMessage:this.signStandardMessages.bind(this)},"solana:signTransaction":{version:`1.0.0`,supportedTransactionVersions:[`legacy`,0],signTransaction:this.signStandardTransactions.bind(this)},"solana:signAndSendTransaction":{version:`1.0.0`,supportedTransactionVersions:[`legacy`,0],signAndSendTransaction:this.signAndSendStandardTransactions.bind(this)}}}get ui(){return this.uiMessageManager}getAccountStatus(){return{authenticated:this.loginMethod!==null,loginMethod:this.loginMethod,activeMode:this.loginMethod?this.accountMode:null,mode:this.accountMode,conversion:this.loginMethod?this.lastKnownConversion:`not_required`,tap:null,squid:null,accounts:this._accounts[0]?{solana:this._accounts[0].address}:{}}}get session(){return{login:()=>this.login(),logout:()=>this.logout(),getLoginMethod:()=>this.getLoginMethod(),getAccountStatus:()=>this.getCanonicalAccountStatus()}}async getCanonicalAccountStatus(){await this.ensureInitialized();let e=await this.postRequestAndWait({method:t.waap_getAccountStatus,params:[],interactionRequired:!1});if(e.error)throw Error(e.error.message||`Failed to read WaaP status`);let n=e.data;return this.syncLoginMethodFromCanonicalStatus(n),n?.conversion&&(this.lastKnownConversion=n.conversion),n}setAccountMode(e){this.accountMode=e,this.initializerPromise=null,this.initializedIframeWindow=null}async selectAccountMode(e,n={}){await this.walletMessageManager.pingIframe(),await this.postRequestAndWait({method:t.set_signing_mode,params:[o(e,n)],interactionRequired:!1})}setLoginMethod(e){this.loginMethod=e,e===null&&(this._accounts=[],this.notifyChange({accounts:[]}))}getLoginMethod(){return this.loginMethod}async login(){await this.ensureInitialized();let e=await this.restoreSession();if(e)return e;let n=(await this.postRequestAndWait({method:t.login,params:[],interactionRequired:!0})).data;return n!==`waap`&&n!==`human`&&n!==`injected`&&n!==`walletconnect`?(this.loginMethod=null,null):(this.loginMethod=n,n)}async logout(){this.lastKnownConversion=`pending`,await this.ensureInitialized(),await this.postRequestAndWait({method:t.logout,params:[],interactionRequired:!1}),this.loginMethod=null,this._accounts=[],this.notifyChange({accounts:[]})}async refreshAccounts(){try{await this.ensureInitialized();let e=await this.postRequestAndWait({method:`solana_connect`,params:[{silent:!0}],interactionRequired:!1});if(e.error)return this._accounts=[],{accounts:[]};let t=this.normalizeAccounts(e.data?.accounts||[]);return this._accounts=t,{accounts:this._accounts}}catch{return this._accounts=[],{accounts:[]}}}normalizeAccounts(e){return e.map(e=>({address:e.address,publicKey:e.publicKey instanceof Uint8Array?e.publicKey:new Uint8Array(e.publicKey??[]),chains:e.chains??this._chains,features:e.features??[]}))}async connect(e){if(!this.loginMethod)throw new r(`not_authenticated`,`Not authenticated: call login() before connect().`,{operation:{chain:`solana`,method:`solana_connect`}});await this.ensureInitialized();let t=await this.postRequestAndWait({method:`solana_connect`,params:[e||{}],interactionRequired:!e?.silent,signal:e?.signal,timeoutMs:e?.timeoutMs});if(t.error)throw Error(t.error.message||`Failed to connect`);let n=this.normalizeAccounts(t.data?.accounts||[]);return this._accounts=n,this.notifyChange({accounts:this._accounts}),e?.silent||this.internalEventEmitter.emit(`connect`),this.internalEventEmitter.emit(`accountsChanged`,this._accounts.map(e=>e.address)),{accounts:this._accounts}}async restoreSession(){try{let e=await this.getCanonicalAccountStatus();if(e.authenticated&&(e.loginMethod===`waap`||e.loginMethod===`human`||e.loginMethod===`injected`||e.loginMethod===`walletconnect`))return this.loginMethod=e.loginMethod,e.loginMethod}catch{}return null}syncLoginMethodFromCanonicalStatus(e){let t=e.authenticated&&(e.loginMethod===`waap`||e.loginMethod===`human`||e.loginMethod===`injected`||e.loginMethod===`walletconnect`)?e.loginMethod:null;t!==this.loginMethod&&this.setLoginMethod(t)}async disconnect(){await this.ensureInitialized(),await this.postRequestAndWait({method:`solana_disconnect`,params:[],interactionRequired:!1}),this._accounts=[],this.notifyChange({accounts:[]})}async signMessage(e){await this.ensureInitialized();let t=e.account.address;if(!this._accounts.some(e=>e.address===t))throw Error(`Account ${t} is not connected`);let n=await this.postRequestAndWait({method:`solana_signMessage`,params:[{message:Array.from(e.message),account:t}],interactionRequired:!0,signal:e.signal,timeoutMs:e.timeoutMs});if(n.error)throw Error(n.error.message||`Failed to sign message`);return{signedMessage:new Uint8Array(n.data.signedMessage),signature:new Uint8Array(n.data.signature)}}async signTransaction(e){await this.ensureInitialized();let t=e.account.address;if(!this._accounts.some(e=>e.address===t))throw Error(`Account ${t} is not connected`);let n=this.resolveTransactionBytes(e.transaction),r=await this.postRequestAndWait({method:`solana_signTransaction`,params:[{transaction:Array.from(n),account:t,chain:e.chain,withPT:e.withPT}],interactionRequired:!0,signal:e.signal,timeoutMs:e.timeoutMs});if(r.error)throw Error(r.error.message||`Failed to sign transaction`);return{signedTransaction:new Uint8Array(r.data.signedTransaction),signature:new Uint8Array(r.data.signature)}}async signAndSendTransaction(e){await this.ensureInitialized();let t=e.account.address;if(!this._accounts.some(e=>e.address===t))throw Error(`Account ${t} is not connected`);let n=this.resolveTransactionBytes(e.transaction),r=await this.postRequestAndWait({method:`solana_signAndSendTransaction`,params:[{transaction:Array.from(n),account:t,chain:e.chain,options:e.options,withPT:e.withPT}],interactionRequired:!0,signal:e.signal,timeoutMs:e.timeoutMs});if(r.error)throw Error(r.error.message||`Failed to sign and send transaction`);return{signature:r.data.signature}}async signStandardMessages(...e){let t=[];for(let n of e){let e=await this.signMessage({account:n.account,message:n.message});t.push({...e,signatureType:`ed25519`})}return t}async signStandardTransactions(...e){let t=[];for(let n of e){let e=await this.signTransaction({account:n.account,transaction:n.transaction,chain:this.asSupportedChain(n.chain)});t.push({signedTransaction:e.signedTransaction})}return t}async signAndSendStandardTransactions(...e){let t=[];for(let n of e){let e=await this.signAndSendTransaction({account:n.account,transaction:n.transaction,chain:this.asSupportedChain(n.chain),options:this.broadcastOptions(n.options)});t.push({signature:p(e.signature)})}return t}asSupportedChain(e){if(e!==void 0){if(this._chains.includes(e))return e;throw new r(`unsupported_input`,`Unsupported Solana Wallet Standard chain: ${e}`,{operation:{chain:`solana`,method:`wallet_standard`}})}}broadcastOptions(e){if(e?.preflightCommitment!==void 0||e?.minContextSlot!==void 0||e?.commitment!==void 0)throw new r(`unsupported_input`,`WaaP does not support Wallet Standard RPC commitment options; configure the dapp RPC instead.`,{operation:{chain:`solana`,method:`wallet_standard`}});return e?{skipPreflight:e.skipPreflight,maxRetries:e.maxRetries}:void 0}async requestPermissionToken(e){await this.ensureInitialized();let n={...e,walletMode:this.accountMode},r=await this.postRequestAndWait({method:t.waap_requestPermissionToken,params:[n],interactionRequired:!0});if(r.error)throw Error(r.error.message||`Failed to request permission token`);return r.data}async getPermissionTokenStatus(e){return await this.ensureInitialized(),(await this.postRequestAndWait({method:t.waap_getPermissionTokenStatus,params:[e],interactionRequired:!1})).data}async clearPermissionToken(e){return await this.ensureInitialized(),(await this.postRequestAndWait({method:t.waap_clearPermissionToken,params:[e],interactionRequired:!1})).data}resolveTransactionBytes(e){if(e instanceof Uint8Array)return e;if(Array.isArray(e))return new Uint8Array(e);if(e&&typeof e.serialize==`function`){let t=e.serialize();return t instanceof Uint8Array?t:new Uint8Array(t)}throw Error(`Unsupported transaction format. Pass serialized bytes or a @solana/web3.js Transaction.`)}on(e,t){return e===`change`?(this.changeListeners.add(t),()=>{this.changeListeners.delete(t)}):(this.internalEventEmitter.on(e,t),()=>{this.internalEventEmitter.removeListener(e,t)})}removeListener(e,t){if(e===`change`){this.changeListeners.delete(t);return}this.internalEventEmitter.removeListener(e,t)}async postRequestAndWait(n){let r;try{n.interactionRequired&&c({layout:n.method===t.login?`auth`:`signing`}),r=await this.walletMessageManager.postSilkRequest({method:n.method,params:n.params,interactionRequired:n.interactionRequired});let e=await l({eventEmitter:this.internalEventEmitter,id:r,method:n.method,interactionRequired:n.interactionRequired,signal:n.signal,timeoutMs:n.timeoutMs,onCancel:()=>{this.walletMessageManager.cancelSilkRequest(r,n.method),n.interactionRequired&&a()}});if(e.error)throw Error(e.error.message);return e}catch(t){throw n.interactionRequired&&r===void 0&&a(),e(t,{chain:`solana`,method:String(n.method),requestId:r})}}notifyChange(e){Array.from(this.changeListeners).forEach(t=>{t(e)})}};function p(e){let t=[];for(let n of e){let e=`123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz`.indexOf(n);if(e<0)throw Error(`Invalid base58 transaction signature`);for(let n=0;n<t.length;n+=1)e+=t[n]*58,t[n]=e&255,e>>=8;for(;e>0;)t.push(e&255),e>>=8}let n=0;for(;n<e.length&&e[n]===`1`;)n+=1;return new Uint8Array([...Array(n).fill(0),...t.reverse()])}export{f as t};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
//#region src/lib/preload.d.ts
|
|
2
|
+
/** Any public WaaP facade that can warm the shared wallet iframe. */
|
|
3
|
+
interface WaaPPreloadTarget {
|
|
4
|
+
preload(): Promise<void>;
|
|
5
|
+
}
|
|
6
|
+
interface WaaPIdlePreloadOptions {
|
|
7
|
+
/** Browser deadline for an idle callback. Default: 2 seconds. */
|
|
8
|
+
timeoutMs?: number;
|
|
9
|
+
/** Observes a best-effort warmup failure without making page startup fail. */
|
|
10
|
+
onError?: (error: unknown) => void;
|
|
11
|
+
}
|
|
12
|
+
type CancelWaaPPreload = () => void;
|
|
13
|
+
/**
|
|
14
|
+
* Warm an already-created WaaP facade when the browser is idle. It never opens
|
|
15
|
+
* wallet UI, and cancellation is useful when the embedding route unmounts.
|
|
16
|
+
*
|
|
17
|
+
* Use this after the host page's LCP. For a likely immediate action (for
|
|
18
|
+
* example Connect button hover/focus), call `target.preload()` directly.
|
|
19
|
+
*/
|
|
20
|
+
declare const preloadWaaPOnIdle: (target: WaaPPreloadTarget, options?: WaaPIdlePreloadOptions) => CancelWaaPPreload;
|
|
21
|
+
//#endregion
|
|
22
|
+
//#region src/lib/WaaPError.d.ts
|
|
23
|
+
/** Stable, safe error vocabulary for non-EIP-1193 SDK facades. */
|
|
24
|
+
type WaaPErrorCode = 'cancelled' | 'timeout' | 'user_rejected' | 'policy_rejected' |
|
|
25
|
+
/**
|
|
26
|
+
* The user's gas tank cannot cover a fee the operation is billed. Distinct
|
|
27
|
+
* from `wallet_error` because it is the user's to fix and retrying changes
|
|
28
|
+
* nothing until they top up — the same split the server draws between a 402
|
|
29
|
+
* and a 502.
|
|
30
|
+
*/
|
|
31
|
+
'insufficient_balance' | 'not_authenticated' | 'not_connected' | 'unsupported_input' | 'wallet_error' | 'maintenance' | 'unknown';
|
|
32
|
+
type WaaPOperationMetadata = {
|
|
33
|
+
/**
|
|
34
|
+
* The chain the failed operation targeted. Declared structurally rather than
|
|
35
|
+
* as `WaaPChain` so the error vocabulary stays free of the initializer graph.
|
|
36
|
+
*/
|
|
37
|
+
chain?: 'evm' | 'sui' | 'solana';
|
|
38
|
+
method?: string;
|
|
39
|
+
requestId?: string;
|
|
40
|
+
};
|
|
41
|
+
declare class WaaPError extends Error {
|
|
42
|
+
readonly code: WaaPErrorCode;
|
|
43
|
+
readonly operation?: WaaPOperationMetadata;
|
|
44
|
+
readonly cause?: unknown;
|
|
45
|
+
constructor(code: WaaPErrorCode, message: string, options?: {
|
|
46
|
+
cause?: unknown;
|
|
47
|
+
operation?: WaaPOperationMetadata;
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
declare function normalizeWaaPError(error: unknown, operation?: WaaPOperationMetadata): WaaPError;
|
|
51
|
+
//#endregion
|
|
52
|
+
export { CancelWaaPPreload as a, preloadWaaPOnIdle as c, normalizeWaaPError as i, WaaPErrorCode as n, WaaPIdlePreloadOptions as o, WaaPOperationMetadata as r, WaaPPreloadTarget as s, WaaPError as t };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
//#region src/lib/preload.d.ts
|
|
2
|
+
/** Any public WaaP facade that can warm the shared wallet iframe. */
|
|
3
|
+
interface WaaPPreloadTarget {
|
|
4
|
+
preload(): Promise<void>;
|
|
5
|
+
}
|
|
6
|
+
interface WaaPIdlePreloadOptions {
|
|
7
|
+
/** Browser deadline for an idle callback. Default: 2 seconds. */
|
|
8
|
+
timeoutMs?: number;
|
|
9
|
+
/** Observes a best-effort warmup failure without making page startup fail. */
|
|
10
|
+
onError?: (error: unknown) => void;
|
|
11
|
+
}
|
|
12
|
+
type CancelWaaPPreload = () => void;
|
|
13
|
+
/**
|
|
14
|
+
* Warm an already-created WaaP facade when the browser is idle. It never opens
|
|
15
|
+
* wallet UI, and cancellation is useful when the embedding route unmounts.
|
|
16
|
+
*
|
|
17
|
+
* Use this after the host page's LCP. For a likely immediate action (for
|
|
18
|
+
* example Connect button hover/focus), call `target.preload()` directly.
|
|
19
|
+
*/
|
|
20
|
+
declare const preloadWaaPOnIdle: (target: WaaPPreloadTarget, options?: WaaPIdlePreloadOptions) => CancelWaaPPreload;
|
|
21
|
+
//#endregion
|
|
22
|
+
//#region src/lib/WaaPError.d.ts
|
|
23
|
+
/** Stable, safe error vocabulary for non-EIP-1193 SDK facades. */
|
|
24
|
+
type WaaPErrorCode = 'cancelled' | 'timeout' | 'user_rejected' | 'policy_rejected' |
|
|
25
|
+
/**
|
|
26
|
+
* The user's gas tank cannot cover a fee the operation is billed. Distinct
|
|
27
|
+
* from `wallet_error` because it is the user's to fix and retrying changes
|
|
28
|
+
* nothing until they top up — the same split the server draws between a 402
|
|
29
|
+
* and a 502.
|
|
30
|
+
*/
|
|
31
|
+
'insufficient_balance' | 'not_authenticated' | 'not_connected' | 'unsupported_input' | 'wallet_error' | 'maintenance' | 'unknown';
|
|
32
|
+
type WaaPOperationMetadata = {
|
|
33
|
+
/**
|
|
34
|
+
* The chain the failed operation targeted. Declared structurally rather than
|
|
35
|
+
* as `WaaPChain` so the error vocabulary stays free of the initializer graph.
|
|
36
|
+
*/
|
|
37
|
+
chain?: 'evm' | 'sui' | 'solana';
|
|
38
|
+
method?: string;
|
|
39
|
+
requestId?: string;
|
|
40
|
+
};
|
|
41
|
+
declare class WaaPError extends Error {
|
|
42
|
+
readonly code: WaaPErrorCode;
|
|
43
|
+
readonly operation?: WaaPOperationMetadata;
|
|
44
|
+
readonly cause?: unknown;
|
|
45
|
+
constructor(code: WaaPErrorCode, message: string, options?: {
|
|
46
|
+
cause?: unknown;
|
|
47
|
+
operation?: WaaPOperationMetadata;
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
declare function normalizeWaaPError(error: unknown, operation?: WaaPOperationMetadata): WaaPError;
|
|
51
|
+
//#endregion
|
|
52
|
+
export { CancelWaaPPreload as a, preloadWaaPOnIdle as c, normalizeWaaPError as i, WaaPErrorCode as n, WaaPIdlePreloadOptions as o, WaaPOperationMetadata as r, WaaPPreloadTarget as s, WaaPError as t };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { D as
|
|
1
|
+
import { D as SilkRequest, N as SILK_METHOD, O as SilkRequestCancellation, P as SilkNotificationData, k as SilkResponse } from "./types-x7TOncUp.js";
|
|
2
2
|
//#region src/lib/WalletMessageManager.d.ts
|
|
3
3
|
type PostSilkRequestArgs = {
|
|
4
4
|
method: keyof typeof SILK_METHOD;
|
|
@@ -26,12 +26,25 @@ interface SquidLifecycleNotification {
|
|
|
26
26
|
* Listener interface for WalletMessageManager
|
|
27
27
|
*/
|
|
28
28
|
interface MessageListenerConfig {
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Optional so a listener interested only in notifications does not have to
|
|
31
|
+
* pass stubs. `shouldHandleTerminalResponse` consumes the id, so a second
|
|
32
|
+
* registration with a no-op `handleResponse` would swallow the response for
|
|
33
|
+
* whichever entry the dispatcher reached first -- correct only by
|
|
34
|
+
* registration order, and silently wrong if that order ever changed.
|
|
35
|
+
*/
|
|
36
|
+
handleResponse?: (response: SilkResponse) => void;
|
|
37
|
+
handleRequest?: (request: SilkRequest) => void;
|
|
31
38
|
onReceiveConnectNotif?: () => void;
|
|
32
39
|
onAccountChanged?: (newAccount: string) => void;
|
|
33
40
|
onAsyncTxNotification?: (notification: AsyncTxNotification) => void;
|
|
34
41
|
onSquidLifecycleNotification?: (notification: SquidLifecycleNotification) => void;
|
|
42
|
+
/**
|
|
43
|
+
* A native social login finished in the system browser. The wallet keeps the
|
|
44
|
+
* originating `login` request open across that hand-off, so this is the only
|
|
45
|
+
* signal that it is over.
|
|
46
|
+
*/
|
|
47
|
+
onAuthComplete?: (result: 'success' | 'error') => void;
|
|
35
48
|
}
|
|
36
49
|
type WalletHandshakeDiagnostics = {
|
|
37
50
|
walletOrigin: string;
|
|
@@ -121,48 +134,4 @@ declare const subscribeWaaPIframeLifecycle: (listener: (event: WaaPIframeLifecyc
|
|
|
121
134
|
*/
|
|
122
135
|
declare const getWaaPIframeDiagnostics: () => WaaPIframeDiagnostics;
|
|
123
136
|
//#endregion
|
|
124
|
-
|
|
125
|
-
/** Any public WaaP facade that can warm the shared wallet iframe. */
|
|
126
|
-
interface WaaPPreloadTarget {
|
|
127
|
-
preload(): Promise<void>;
|
|
128
|
-
}
|
|
129
|
-
interface WaaPIdlePreloadOptions {
|
|
130
|
-
/** Browser deadline for an idle callback. Default: 2 seconds. */
|
|
131
|
-
timeoutMs?: number;
|
|
132
|
-
/** Observes a best-effort warmup failure without making page startup fail. */
|
|
133
|
-
onError?: (error: unknown) => void;
|
|
134
|
-
}
|
|
135
|
-
type CancelWaaPPreload = () => void;
|
|
136
|
-
/**
|
|
137
|
-
* Warm an already-created WaaP facade when the browser is idle. It never opens
|
|
138
|
-
* wallet UI, and cancellation is useful when the embedding route unmounts.
|
|
139
|
-
*
|
|
140
|
-
* Use this after the host page's LCP. For a likely immediate action (for
|
|
141
|
-
* example Connect button hover/focus), call `target.preload()` directly.
|
|
142
|
-
*/
|
|
143
|
-
declare const preloadWaaPOnIdle: (target: WaaPPreloadTarget, options?: WaaPIdlePreloadOptions) => CancelWaaPPreload;
|
|
144
|
-
//#endregion
|
|
145
|
-
//#region src/lib/WaaPError.d.ts
|
|
146
|
-
/** Stable, safe error vocabulary for non-EIP-1193 SDK facades. */
|
|
147
|
-
type WaaPErrorCode = 'cancelled' | 'timeout' | 'user_rejected' | 'policy_rejected' | 'not_authenticated' | 'not_connected' | 'unsupported_input' | 'wallet_error' | 'maintenance' | 'unknown';
|
|
148
|
-
type WaaPOperationMetadata = {
|
|
149
|
-
/**
|
|
150
|
-
* The chain the failed operation targeted. Declared structurally rather than
|
|
151
|
-
* as `WaaPChain` so the error vocabulary stays free of the initializer graph.
|
|
152
|
-
*/
|
|
153
|
-
chain?: 'evm' | 'sui' | 'solana';
|
|
154
|
-
method?: string;
|
|
155
|
-
requestId?: string;
|
|
156
|
-
};
|
|
157
|
-
declare class WaaPError extends Error {
|
|
158
|
-
readonly code: WaaPErrorCode;
|
|
159
|
-
readonly operation?: WaaPOperationMetadata;
|
|
160
|
-
readonly cause?: unknown;
|
|
161
|
-
constructor(code: WaaPErrorCode, message: string, options?: {
|
|
162
|
-
cause?: unknown;
|
|
163
|
-
operation?: WaaPOperationMetadata;
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
declare function normalizeWaaPError(error: unknown, operation?: WaaPOperationMetadata): WaaPError;
|
|
167
|
-
//#endregion
|
|
168
|
-
export { CancelWaaPPreload as a, preloadWaaPOnIdle as c, WaaPIframeLifecyclePhase as d, getWaaPIframeDiagnostics as f, WalletMessageManager as h, normalizeWaaPError as i, WaaPIframeDiagnostics as l, PostSilkRequestArgs as m, WaaPErrorCode as n, WaaPIdlePreloadOptions as o, subscribeWaaPIframeLifecycle as p, WaaPOperationMetadata as r, WaaPPreloadTarget as s, WaaPError as t, WaaPIframeLifecycleEvent as u };
|
|
137
|
+
export { subscribeWaaPIframeLifecycle as a, getWaaPIframeDiagnostics as i, WaaPIframeLifecycleEvent as n, PostSilkRequestArgs as o, WaaPIframeLifecyclePhase as r, WalletMessageManager as s, WaaPIframeDiagnostics as t };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { D as
|
|
1
|
+
import { D as SilkRequest, N as SILK_METHOD, O as SilkRequestCancellation, P as SilkNotificationData, k as SilkResponse } from "./types-x7TOncUp.mjs";
|
|
2
2
|
//#region src/lib/WalletMessageManager.d.ts
|
|
3
3
|
type PostSilkRequestArgs = {
|
|
4
4
|
method: keyof typeof SILK_METHOD;
|
|
@@ -26,12 +26,25 @@ interface SquidLifecycleNotification {
|
|
|
26
26
|
* Listener interface for WalletMessageManager
|
|
27
27
|
*/
|
|
28
28
|
interface MessageListenerConfig {
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Optional so a listener interested only in notifications does not have to
|
|
31
|
+
* pass stubs. `shouldHandleTerminalResponse` consumes the id, so a second
|
|
32
|
+
* registration with a no-op `handleResponse` would swallow the response for
|
|
33
|
+
* whichever entry the dispatcher reached first -- correct only by
|
|
34
|
+
* registration order, and silently wrong if that order ever changed.
|
|
35
|
+
*/
|
|
36
|
+
handleResponse?: (response: SilkResponse) => void;
|
|
37
|
+
handleRequest?: (request: SilkRequest) => void;
|
|
31
38
|
onReceiveConnectNotif?: () => void;
|
|
32
39
|
onAccountChanged?: (newAccount: string) => void;
|
|
33
40
|
onAsyncTxNotification?: (notification: AsyncTxNotification) => void;
|
|
34
41
|
onSquidLifecycleNotification?: (notification: SquidLifecycleNotification) => void;
|
|
42
|
+
/**
|
|
43
|
+
* A native social login finished in the system browser. The wallet keeps the
|
|
44
|
+
* originating `login` request open across that hand-off, so this is the only
|
|
45
|
+
* signal that it is over.
|
|
46
|
+
*/
|
|
47
|
+
onAuthComplete?: (result: 'success' | 'error') => void;
|
|
35
48
|
}
|
|
36
49
|
type WalletHandshakeDiagnostics = {
|
|
37
50
|
walletOrigin: string;
|
|
@@ -121,48 +134,4 @@ declare const subscribeWaaPIframeLifecycle: (listener: (event: WaaPIframeLifecyc
|
|
|
121
134
|
*/
|
|
122
135
|
declare const getWaaPIframeDiagnostics: () => WaaPIframeDiagnostics;
|
|
123
136
|
//#endregion
|
|
124
|
-
|
|
125
|
-
/** Any public WaaP facade that can warm the shared wallet iframe. */
|
|
126
|
-
interface WaaPPreloadTarget {
|
|
127
|
-
preload(): Promise<void>;
|
|
128
|
-
}
|
|
129
|
-
interface WaaPIdlePreloadOptions {
|
|
130
|
-
/** Browser deadline for an idle callback. Default: 2 seconds. */
|
|
131
|
-
timeoutMs?: number;
|
|
132
|
-
/** Observes a best-effort warmup failure without making page startup fail. */
|
|
133
|
-
onError?: (error: unknown) => void;
|
|
134
|
-
}
|
|
135
|
-
type CancelWaaPPreload = () => void;
|
|
136
|
-
/**
|
|
137
|
-
* Warm an already-created WaaP facade when the browser is idle. It never opens
|
|
138
|
-
* wallet UI, and cancellation is useful when the embedding route unmounts.
|
|
139
|
-
*
|
|
140
|
-
* Use this after the host page's LCP. For a likely immediate action (for
|
|
141
|
-
* example Connect button hover/focus), call `target.preload()` directly.
|
|
142
|
-
*/
|
|
143
|
-
declare const preloadWaaPOnIdle: (target: WaaPPreloadTarget, options?: WaaPIdlePreloadOptions) => CancelWaaPPreload;
|
|
144
|
-
//#endregion
|
|
145
|
-
//#region src/lib/WaaPError.d.ts
|
|
146
|
-
/** Stable, safe error vocabulary for non-EIP-1193 SDK facades. */
|
|
147
|
-
type WaaPErrorCode = 'cancelled' | 'timeout' | 'user_rejected' | 'policy_rejected' | 'not_authenticated' | 'not_connected' | 'unsupported_input' | 'wallet_error' | 'maintenance' | 'unknown';
|
|
148
|
-
type WaaPOperationMetadata = {
|
|
149
|
-
/**
|
|
150
|
-
* The chain the failed operation targeted. Declared structurally rather than
|
|
151
|
-
* as `WaaPChain` so the error vocabulary stays free of the initializer graph.
|
|
152
|
-
*/
|
|
153
|
-
chain?: 'evm' | 'sui' | 'solana';
|
|
154
|
-
method?: string;
|
|
155
|
-
requestId?: string;
|
|
156
|
-
};
|
|
157
|
-
declare class WaaPError extends Error {
|
|
158
|
-
readonly code: WaaPErrorCode;
|
|
159
|
-
readonly operation?: WaaPOperationMetadata;
|
|
160
|
-
readonly cause?: unknown;
|
|
161
|
-
constructor(code: WaaPErrorCode, message: string, options?: {
|
|
162
|
-
cause?: unknown;
|
|
163
|
-
operation?: WaaPOperationMetadata;
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
declare function normalizeWaaPError(error: unknown, operation?: WaaPOperationMetadata): WaaPError;
|
|
167
|
-
//#endregion
|
|
168
|
-
export { CancelWaaPPreload as a, preloadWaaPOnIdle as c, WaaPIframeLifecyclePhase as d, getWaaPIframeDiagnostics as f, WalletMessageManager as h, normalizeWaaPError as i, WaaPIframeDiagnostics as l, PostSilkRequestArgs as m, WaaPErrorCode as n, WaaPIdlePreloadOptions as o, subscribeWaaPIframeLifecycle as p, WaaPOperationMetadata as r, WaaPPreloadTarget as s, WaaPError as t, WaaPIframeLifecycleEvent as u };
|
|
137
|
+
export { subscribeWaaPIframeLifecycle as a, getWaaPIframeDiagnostics as i, WaaPIframeLifecycleEvent as n, PostSilkRequestArgs as o, WaaPIframeLifecyclePhase as r, WalletMessageManager as s, WaaPIframeDiagnostics as t };
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { F as WaaPSdkPlatform, l as SilkEthereumProviderInterface, n as InitSilkOptions } from "./types-x7TOncUp.mjs";
|
|
2
|
+
import { i as getWaaPIframeDiagnostics } from "./WalletModalController-wIHBGOVd.mjs";
|
|
3
|
+
import { y as WaaPSolanaProviderInterface } from "./types-Bfz205sD.mjs";
|
|
4
|
+
//#region src/lib/bridge/mobileBridge.d.ts
|
|
5
|
+
type MobileBridgeOptions = {
|
|
6
|
+
/** Serialized outbound envelopes, host-bound. */
|
|
7
|
+
post: (message: string) => void;
|
|
8
|
+
/**
|
|
9
|
+
* Deferred so the WebView can load the bridge page before the wallet iframe
|
|
10
|
+
* is mounted, and so tests can drive a stub provider.
|
|
11
|
+
*/
|
|
12
|
+
createProvider: () => SilkEthereumProviderInterface;
|
|
13
|
+
/**
|
|
14
|
+
* The Solana facade over the same wallet iframe. Optional so a host that only
|
|
15
|
+
* needs EVM -- and every existing test -- keeps working unchanged.
|
|
16
|
+
*/
|
|
17
|
+
createSolanaProvider?: () => WaaPSolanaProviderInterface;
|
|
18
|
+
/**
|
|
19
|
+
* Stamped on every outbound message so the host can tell this frame apart
|
|
20
|
+
* from the cross-origin frames that share its JavaScript channel. See
|
|
21
|
+
* `BridgeResponse['token']`.
|
|
22
|
+
*/
|
|
23
|
+
token?: string;
|
|
24
|
+
};
|
|
25
|
+
type MobileBridge = {
|
|
26
|
+
handleMessage: (raw: unknown) => void;
|
|
27
|
+
dispose: () => void;
|
|
28
|
+
};
|
|
29
|
+
declare const createMobileBridge: (options: MobileBridgeOptions) => MobileBridge;
|
|
30
|
+
//#endregion
|
|
31
|
+
//#region src/lib/bridge/evmMethods.d.ts
|
|
32
|
+
/**
|
|
33
|
+
* The EIP-1193 methods `evm.request` may forward.
|
|
34
|
+
*
|
|
35
|
+
* `SILK_METHOD` is not usable as the allowlist: it also carries portal-admin
|
|
36
|
+
* and wallet-configuration methods (`project_init`, `gastank_topup`,
|
|
37
|
+
* `customization_update`, `set_project`, `set_custom_config`) that a native
|
|
38
|
+
* application must never be able to reach through the escape hatch. The list is
|
|
39
|
+
* enumerated rather than derived from an `eth_`/`wallet_` prefix so adding a
|
|
40
|
+
* method to the enum cannot silently widen the native surface.
|
|
41
|
+
*/
|
|
42
|
+
declare const BRIDGE_EVM_METHODS: readonly string[];
|
|
43
|
+
//#endregion
|
|
44
|
+
//#region src/lib/bridge/protocol.d.ts
|
|
45
|
+
/**
|
|
46
|
+
* Wire protocol between a native host (Flutter/Dart) and the browser SDK
|
|
47
|
+
* running in a WebView bridge page.
|
|
48
|
+
*
|
|
49
|
+
* The host is untrusted input. Every inbound message is parsed defensively and
|
|
50
|
+
* anything that is not a well-formed request for a known method is refused
|
|
51
|
+
* without reaching the SDK.
|
|
52
|
+
*/
|
|
53
|
+
declare const BRIDGE_PROTOCOL_VERSION = 1;
|
|
54
|
+
type BridgeMethod = 'session.login' | 'session.logout' | 'session.status' | 'evm.connect' | 'evm.request' | 'solana.connect' | 'solana.disconnect' | 'solana.accounts' | 'solana.signMessage' | 'solana.signTransaction' | 'solana.signAndSendTransaction' | 'sdk.preload' | 'sdk.destroy';
|
|
55
|
+
/**
|
|
56
|
+
* Codes the Dart layer switches on. They are deliberately not the SDK's
|
|
57
|
+
* `WaaPErrorCode` values: the native surface owns its own stable vocabulary and
|
|
58
|
+
* must not break when the SDK's internal codes are extended.
|
|
59
|
+
*/
|
|
60
|
+
type BridgeErrorCode = 'cancelled' | 'timeout' | 'userRejected' | 'policyRejected' | 'insufficientBalance' | 'notAuthenticated' | 'notConnected' | 'unsupportedInput' | 'unsupportedMethod' | 'walletError' | 'maintenance' | 'protocolError' | 'bridgeUnavailable' | 'serializationFailed' | 'unknown';
|
|
61
|
+
type BridgeError = {
|
|
62
|
+
code: BridgeErrorCode;
|
|
63
|
+
message: string;
|
|
64
|
+
/** Present only when the wallet supplied an EIP-1193 numeric code. */
|
|
65
|
+
eip1193Code?: number;
|
|
66
|
+
method?: string;
|
|
67
|
+
};
|
|
68
|
+
type BridgeRequest = {
|
|
69
|
+
version: number;
|
|
70
|
+
kind: 'request';
|
|
71
|
+
id: string;
|
|
72
|
+
method: BridgeMethod;
|
|
73
|
+
params?: unknown;
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* `token` authenticates the sender as the bridge page's main frame.
|
|
77
|
+
*
|
|
78
|
+
* A WebView JavaScript channel is not origin-scoped. On Android it is backed by
|
|
79
|
+
* `addJavascriptInterface`, which injects the object into *every* frame and
|
|
80
|
+
* tells the host nothing about which one called — and this page deliberately
|
|
81
|
+
* contains the wallet, cross-origin, which in turn loads third-party login
|
|
82
|
+
* frames. Any of them could otherwise post a forged `accountsChanged` or a
|
|
83
|
+
* forged `session.status` response straight to the native layer.
|
|
84
|
+
*
|
|
85
|
+
* The host mints a secret per page load and hands it to the main frame only.
|
|
86
|
+
* A cross-origin subframe cannot read a main-frame variable, so it cannot
|
|
87
|
+
* produce this value, and the host drops anything that arrives without it.
|
|
88
|
+
*/
|
|
89
|
+
type BridgeResponse = {
|
|
90
|
+
version: number;
|
|
91
|
+
kind: 'response';
|
|
92
|
+
id: string;
|
|
93
|
+
result?: unknown;
|
|
94
|
+
error?: BridgeError;
|
|
95
|
+
token?: string;
|
|
96
|
+
};
|
|
97
|
+
type BridgeEvent = {
|
|
98
|
+
version: number;
|
|
99
|
+
kind: 'event';
|
|
100
|
+
event: string;
|
|
101
|
+
data?: unknown;
|
|
102
|
+
token?: string;
|
|
103
|
+
};
|
|
104
|
+
type ParsedHostMessage = {
|
|
105
|
+
ok: true;
|
|
106
|
+
request: BridgeRequest;
|
|
107
|
+
} | {
|
|
108
|
+
ok: false;
|
|
109
|
+
id: string | null;
|
|
110
|
+
error: BridgeError;
|
|
111
|
+
};
|
|
112
|
+
declare const parseHostMessage: (raw: unknown) => ParsedHostMessage;
|
|
113
|
+
//#endregion
|
|
114
|
+
//#region src/bridge.d.ts
|
|
115
|
+
type NativeHostWindow = Window & {
|
|
116
|
+
ReactNativeWebView?: {
|
|
117
|
+
postMessage: (message: string) => void;
|
|
118
|
+
};
|
|
119
|
+
webkit?: {
|
|
120
|
+
messageHandlers?: Record<string, {
|
|
121
|
+
postMessage: (message: string) => void;
|
|
122
|
+
}>;
|
|
123
|
+
};
|
|
124
|
+
[channel: string]: unknown;
|
|
125
|
+
};
|
|
126
|
+
/**
|
|
127
|
+
* Resolve the host channel this WebView exposes. `channel` names the JavaScript
|
|
128
|
+
* interface on Android and the message handler on iOS; both are installed by
|
|
129
|
+
* the native layer before the page loads.
|
|
130
|
+
*/
|
|
131
|
+
declare const resolveNativeHostPost: (channel?: string, scope?: NativeHostWindow) => ((message: string) => void) | null;
|
|
132
|
+
type StartMobileBridgeOptions = {
|
|
133
|
+
init?: InitSilkOptions;
|
|
134
|
+
channel?: string;
|
|
135
|
+
post?: (message: string) => void;
|
|
136
|
+
/**
|
|
137
|
+
* Secret the host minted for this page load, echoed on every outbound
|
|
138
|
+
* message. The channel is shared with every frame in the WebView, including
|
|
139
|
+
* the cross-origin wallet; this is what distinguishes this frame from them.
|
|
140
|
+
*/
|
|
141
|
+
token?: string;
|
|
142
|
+
/**
|
|
143
|
+
* The SDK actually facing the integrator. This bundle is compiled into
|
|
144
|
+
* `waap-sdk-flutter`, so a Flutter session would otherwise report itself as
|
|
145
|
+
* the web SDK, at the web SDK's version. Attribution only.
|
|
146
|
+
*/
|
|
147
|
+
sdkPlatform?: WaaPSdkPlatform;
|
|
148
|
+
sdkVersion?: string;
|
|
149
|
+
};
|
|
150
|
+
/**
|
|
151
|
+
* Wire the bridge to the WebView host and begin accepting host messages.
|
|
152
|
+
*
|
|
153
|
+
* Throws when no host channel is present rather than falling back to a no-op:
|
|
154
|
+
* a silently deaf bridge would leave every native call pending forever.
|
|
155
|
+
*/
|
|
156
|
+
declare const startMobileBridge: (options?: StartMobileBridgeOptions) => MobileBridge;
|
|
157
|
+
//#endregion
|
|
158
|
+
export { BRIDGE_EVM_METHODS, BRIDGE_PROTOCOL_VERSION, type BridgeError, type BridgeErrorCode, type BridgeEvent, type BridgeMethod, type BridgeRequest, type BridgeResponse, type MobileBridge, type MobileBridgeOptions, StartMobileBridgeOptions, createMobileBridge, getWaaPIframeDiagnostics, parseHostMessage, resolveNativeHostPost, startMobileBridge };
|