accounts 0.12.2 → 0.14.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 +35 -0
- package/README.md +6 -5
- package/dist/cli/adapter.d.ts.map +1 -1
- package/dist/cli/adapter.js +76 -69
- package/dist/cli/adapter.js.map +1 -1
- package/dist/core/AccessKey.d.ts +89 -106
- package/dist/core/AccessKey.d.ts.map +1 -1
- package/dist/core/AccessKey.js +230 -210
- package/dist/core/AccessKey.js.map +1 -1
- package/dist/core/Account.d.ts +0 -9
- package/dist/core/Account.d.ts.map +1 -1
- package/dist/core/Account.js +1 -13
- package/dist/core/Account.js.map +1 -1
- package/dist/core/Adapter.d.ts +24 -4
- package/dist/core/Adapter.d.ts.map +1 -1
- package/dist/core/Client.d.ts +1 -1
- package/dist/core/Client.d.ts.map +1 -1
- package/dist/core/Client.js.map +1 -1
- package/dist/core/Provider.d.ts +6 -7
- package/dist/core/Provider.d.ts.map +1 -1
- package/dist/core/Provider.js +73 -77
- package/dist/core/Provider.js.map +1 -1
- package/dist/core/Remote.d.ts +2 -0
- package/dist/core/Remote.d.ts.map +1 -1
- package/dist/core/Remote.js +3 -1
- package/dist/core/Remote.js.map +1 -1
- package/dist/core/Schema.d.ts +17 -7
- package/dist/core/Schema.d.ts.map +1 -1
- package/dist/core/adapters/dialog.d.ts.map +1 -1
- package/dist/core/adapters/dialog.js +126 -131
- package/dist/core/adapters/dialog.js.map +1 -1
- package/dist/core/adapters/local.d.ts.map +1 -1
- package/dist/core/adapters/local.js +92 -105
- package/dist/core/adapters/local.js.map +1 -1
- package/dist/core/adapters/privy.d.ts +164 -0
- package/dist/core/adapters/privy.d.ts.map +1 -0
- package/dist/core/adapters/privy.js +578 -0
- package/dist/core/adapters/privy.js.map +1 -0
- package/dist/core/adapters/turnkey.d.ts.map +1 -1
- package/dist/core/adapters/turnkey.js +136 -133
- package/dist/core/adapters/turnkey.js.map +1 -1
- package/dist/core/internal/AccessKeyTransaction.d.ts +59 -0
- package/dist/core/internal/AccessKeyTransaction.d.ts.map +1 -0
- package/dist/core/internal/AccessKeyTransaction.js +155 -0
- package/dist/core/internal/AccessKeyTransaction.js.map +1 -0
- package/dist/core/zod/rpc.d.ts +71 -4
- package/dist/core/zod/rpc.d.ts.map +1 -1
- package/dist/core/zod/rpc.js +33 -4
- package/dist/core/zod/rpc.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/react-native/adapter.d.ts.map +1 -1
- package/dist/react-native/adapter.js +86 -75
- package/dist/react-native/adapter.js.map +1 -1
- package/dist/server/CliAuth.d.ts +55 -0
- package/dist/server/CliAuth.d.ts.map +1 -1
- package/dist/server/CliAuth.js +18 -1
- package/dist/server/CliAuth.js.map +1 -1
- package/dist/server/Kv.d.ts +19 -9
- package/dist/server/Kv.d.ts.map +1 -1
- package/dist/server/Kv.js +32 -9
- package/dist/server/Kv.js.map +1 -1
- package/dist/server/internal/handlers/auth.d.ts.map +1 -1
- package/dist/server/internal/handlers/auth.js +3 -1
- package/dist/server/internal/handlers/auth.js.map +1 -1
- package/dist/server/internal/handlers/codeAuth.js +1 -1
- package/dist/server/internal/handlers/codeAuth.js.map +1 -1
- package/dist/server/internal/handlers/exchange.js +1 -1
- package/dist/server/internal/handlers/exchange.js.map +1 -1
- package/dist/server/internal/handlers/relay.d.ts +18 -12
- package/dist/server/internal/handlers/relay.d.ts.map +1 -1
- package/dist/server/internal/handlers/relay.js +116 -3
- package/dist/server/internal/handlers/relay.js.map +1 -1
- package/dist/server/internal/handlers/webAuthn.d.ts +6 -1
- package/dist/server/internal/handlers/webAuthn.d.ts.map +1 -1
- package/dist/server/internal/handlers/webAuthn.js +16 -9
- package/dist/server/internal/handlers/webAuthn.js.map +1 -1
- package/package.json +3 -3
- package/src/cli/{Provider.test.ts → Provider.localnet.test.ts} +49 -1
- package/src/cli/adapter.ts +95 -76
- package/src/core/AccessKey.test.ts +563 -560
- package/src/core/AccessKey.ts +327 -327
- package/src/core/Account.test.ts +6 -51
- package/src/core/Account.ts +1 -19
- package/src/core/Adapter.ts +22 -4
- package/src/core/Client.test.ts +1 -1
- package/src/core/Client.ts +1 -1
- package/src/core/Provider.connect.browser.test.ts +1 -1
- package/src/core/{Provider.test.ts → Provider.localnet.test.ts} +98 -32
- package/src/core/Provider.ts +118 -112
- package/src/core/Remote.test.ts +28 -0
- package/src/core/Remote.ts +4 -1
- package/src/core/Schema.test-d.ts +41 -0
- package/src/core/adapters/dialog.test.ts +335 -15
- package/src/core/adapters/dialog.ts +120 -127
- package/src/core/adapters/local.test.ts +1 -1
- package/src/core/adapters/local.ts +95 -119
- package/src/core/adapters/privy.test-d.ts +128 -0
- package/src/core/adapters/privy.test.ts +648 -0
- package/src/core/adapters/privy.ts +811 -0
- package/src/core/adapters/turnkey.test.ts +117 -13
- package/src/core/adapters/turnkey.ts +132 -149
- package/src/core/internal/AccessKeyTransaction.ts +243 -0
- package/src/core/{mppx.test.ts → mppx.localnet.test.ts} +32 -2
- package/src/core/zod/request.test.ts +36 -0
- package/src/core/zod/rpc.test.ts +139 -0
- package/src/core/zod/rpc.ts +44 -10
- package/src/index.ts +1 -1
- package/src/react-native/{Provider.test.ts → Provider.localnet.test.ts} +65 -0
- package/src/react-native/adapter.ts +107 -87
- package/src/server/CliAuth.test-d.ts +23 -0
- package/src/server/CliAuth.test.ts +47 -0
- package/src/server/CliAuth.ts +20 -1
- package/src/server/Handler.test-d.ts +1 -1
- package/src/server/Kv.test.ts +51 -0
- package/src/server/Kv.ts +43 -9
- package/src/server/internal/handlers/auth.test.ts +10 -5
- package/src/server/internal/handlers/auth.ts +4 -1
- package/src/server/internal/handlers/codeAuth.ts +1 -1
- package/src/server/internal/handlers/exchange.ts +1 -1
- package/src/server/internal/handlers/{relay.test.ts → relay.localnet.test.ts} +4 -1
- package/src/server/internal/handlers/relay.ts +139 -14
- package/src/server/internal/handlers/session.test.ts +1 -1
- package/src/server/internal/handlers/webAuthn.test.ts +20 -0
- package/src/server/internal/handlers/webAuthn.ts +24 -12
- /package/src/server/internal/handlers/{exchange.test.ts → exchange.localnet.test.ts} +0 -0
package/src/core/Provider.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { announceProvider } from 'mipd'
|
|
2
2
|
import { Mppx, tempo as mppx_tempo } from 'mppx/client'
|
|
3
3
|
import { Address, Hash, Hex, Json, Provider as ox_Provider, RpcResponse } from 'ox'
|
|
4
|
-
import { KeyAuthorization } from 'ox/tempo'
|
|
5
4
|
import { http, parseUnits, type Chain, type Client as ViemClient, type Transport } from 'viem'
|
|
6
|
-
import {
|
|
5
|
+
import type { JsonRpcAccount } from 'viem/accounts'
|
|
7
6
|
import { parseSiweMessage } from 'viem/siwe'
|
|
8
7
|
import { Actions } from 'viem/tempo'
|
|
8
|
+
import { tempo, tempoDevnet, tempoModerato } from 'viem/tempo/chains'
|
|
9
9
|
import * as z from 'zod/mini'
|
|
10
10
|
|
|
11
11
|
import * as AccessKey from './AccessKey.js'
|
|
@@ -13,6 +13,7 @@ import * as Account from './Account.js'
|
|
|
13
13
|
import type * as Adapter from './Adapter.js'
|
|
14
14
|
import { dialog } from './adapters/dialog.js'
|
|
15
15
|
import * as Client from './Client.js'
|
|
16
|
+
import * as AccessKeyTransaction from './internal/AccessKeyTransaction.js'
|
|
16
17
|
import { withDedupe } from './internal/withDedupe.js'
|
|
17
18
|
import * as Schema from './Schema.js'
|
|
18
19
|
import * as Storage from './Storage.js'
|
|
@@ -25,8 +26,8 @@ export type Provider = ox_Provider.Provider<{ schema: Schema.Ox }> &
|
|
|
25
26
|
ox_Provider.Emitter & {
|
|
26
27
|
/** Configured chains. */
|
|
27
28
|
chains: readonly [Chain, ...Chain[]]
|
|
28
|
-
/** Returns
|
|
29
|
-
getAccount:
|
|
29
|
+
/** Returns the active root account as a viem JSON-RPC account. */
|
|
30
|
+
getAccount(): JsonRpcAccount
|
|
30
31
|
/** Returns local or on-chain publication status for an access key. */
|
|
31
32
|
getAccessKeyStatus(
|
|
32
33
|
options?: getAccessKeyStatus.Options | undefined,
|
|
@@ -271,8 +272,8 @@ export function create(options: create.Options = {}): create.ReturnType {
|
|
|
271
272
|
type FillParams = z.output<typeof Rpc.transactionRequest> & {
|
|
272
273
|
keyAuthorization?: unknown
|
|
273
274
|
}
|
|
275
|
+
const client = getClient({ chainId, feePayer })
|
|
274
276
|
const fill = (params: FillParams) => {
|
|
275
|
-
const client = getClient({ chainId, feePayer })
|
|
276
277
|
const fillRequest = {
|
|
277
278
|
...params,
|
|
278
279
|
chainId: params.chainId ?? client.chain?.id,
|
|
@@ -292,45 +293,38 @@ export function create(options: create.Options = {}): create.ReturnType {
|
|
|
292
293
|
// Inject pending keyAuthorization so the node accounts for
|
|
293
294
|
// key authorization gas during estimation.
|
|
294
295
|
if (!parameters.keyAuthorization) {
|
|
295
|
-
const
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
if (account?.source === 'accessKey') {
|
|
318
|
-
const keyAuth = AccessKey.getPending(account, { store })
|
|
319
|
-
if (keyAuth) {
|
|
296
|
+
const state = store.getState()
|
|
297
|
+
const address =
|
|
298
|
+
parameters.from ?? state.accounts[state.activeAccount]?.address
|
|
299
|
+
if (address) {
|
|
300
|
+
const calls =
|
|
301
|
+
parameters.calls ??
|
|
302
|
+
(parameters.to
|
|
303
|
+
? [
|
|
304
|
+
{
|
|
305
|
+
data: parameters.data,
|
|
306
|
+
to: parameters.to,
|
|
307
|
+
},
|
|
308
|
+
]
|
|
309
|
+
: undefined)
|
|
310
|
+
const transaction = await AccessKeyTransaction.create({
|
|
311
|
+
address,
|
|
312
|
+
calls,
|
|
313
|
+
chainId: parameters.chainId ?? state.chainId,
|
|
314
|
+
client,
|
|
315
|
+
store,
|
|
316
|
+
})
|
|
317
|
+
if (transaction)
|
|
320
318
|
try {
|
|
321
|
-
|
|
319
|
+
return await transaction.fill({
|
|
322
320
|
...parameters,
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
} as never,
|
|
321
|
+
chainId: parameters.chainId ?? state.chainId,
|
|
322
|
+
from: parameters.from ?? address,
|
|
323
|
+
...(feePayer ? { feePayer: true } : {}),
|
|
327
324
|
})
|
|
328
|
-
|
|
329
|
-
} catch (error) {
|
|
330
|
-
AccessKey.invalidate(account, error, { store })
|
|
325
|
+
} catch {
|
|
331
326
|
return await fill(parameters)
|
|
332
327
|
}
|
|
333
|
-
}
|
|
334
328
|
}
|
|
335
329
|
}
|
|
336
330
|
|
|
@@ -574,6 +568,11 @@ export function create(options: create.Options = {}): create.ReturnType {
|
|
|
574
568
|
auth_input as NonNullable<z.output<typeof Rpc.wallet_connect.auth>>,
|
|
575
569
|
)
|
|
576
570
|
: undefined
|
|
571
|
+
if (auth_request && typeof auth_request === 'object' && !auth_request.challenge)
|
|
572
|
+
throw new RpcResponse.InvalidParamsError({
|
|
573
|
+
message:
|
|
574
|
+
'`auth` capability must include either `url` or an explicit `challenge` endpoint.',
|
|
575
|
+
})
|
|
577
576
|
if (auth_request && capabilities?.personalSign)
|
|
578
577
|
throw new RpcResponse.InvalidParamsError({
|
|
579
578
|
message:
|
|
@@ -608,56 +607,67 @@ export function create(options: create.Options = {}): create.ReturnType {
|
|
|
608
607
|
? { message: auth.message }
|
|
609
608
|
: capabilities?.personalSign
|
|
610
609
|
|
|
611
|
-
const {
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
},
|
|
635
|
-
request,
|
|
636
|
-
)
|
|
637
|
-
return await actions.createAccount(
|
|
610
|
+
const {
|
|
611
|
+
accounts,
|
|
612
|
+
auth: auth_capability,
|
|
613
|
+
email,
|
|
614
|
+
keyAuthorization,
|
|
615
|
+
personalSign,
|
|
616
|
+
signature,
|
|
617
|
+
username,
|
|
618
|
+
} = await (async () => {
|
|
619
|
+
if (capabilities?.method === 'register') {
|
|
620
|
+
// If a stored account already has this label, sign in
|
|
621
|
+
// with its credential instead of creating a new one.
|
|
622
|
+
const existing = capabilities.name
|
|
623
|
+
? store
|
|
624
|
+
.getState()
|
|
625
|
+
.accounts.find(
|
|
626
|
+
(a) =>
|
|
627
|
+
'credential' in a &&
|
|
628
|
+
a.label?.toLowerCase() === capabilities.name!.toLowerCase(),
|
|
629
|
+
)
|
|
630
|
+
: undefined
|
|
631
|
+
if (existing && 'credential' in existing)
|
|
632
|
+
return await actions.loadAccounts(
|
|
638
633
|
{
|
|
634
|
+
credentialId: existing.credential?.id,
|
|
639
635
|
digest: capabilities.digest,
|
|
640
636
|
authorizeAccessKey,
|
|
641
|
-
name: capabilities.name ?? 'default',
|
|
642
|
-
userId: capabilities.userId ?? Hex.random(16),
|
|
643
637
|
...(personalSign_request
|
|
644
638
|
? { personalSign: personalSign_request }
|
|
645
639
|
: {}),
|
|
640
|
+
...(capabilities.showDeposit !== undefined
|
|
641
|
+
? { showDeposit: capabilities.showDeposit }
|
|
642
|
+
: {}),
|
|
646
643
|
},
|
|
647
644
|
request,
|
|
648
645
|
)
|
|
649
|
-
|
|
650
|
-
return await actions.loadAccounts(
|
|
646
|
+
return await actions.createAccount(
|
|
651
647
|
{
|
|
652
|
-
|
|
653
|
-
digest: capabilities?.digest,
|
|
648
|
+
digest: capabilities.digest,
|
|
654
649
|
authorizeAccessKey,
|
|
655
|
-
|
|
650
|
+
name: capabilities.name ?? 'default',
|
|
651
|
+
...(capabilities.showDeposit !== undefined
|
|
652
|
+
? { showDeposit: capabilities.showDeposit }
|
|
653
|
+
: {}),
|
|
654
|
+
userId: capabilities.userId ?? Hex.random(16),
|
|
656
655
|
...(personalSign_request ? { personalSign: personalSign_request } : {}),
|
|
657
656
|
},
|
|
658
657
|
request,
|
|
659
658
|
)
|
|
660
|
-
}
|
|
659
|
+
}
|
|
660
|
+
return await actions.loadAccounts(
|
|
661
|
+
{
|
|
662
|
+
credentialId: capabilities?.credentialId,
|
|
663
|
+
digest: capabilities?.digest,
|
|
664
|
+
authorizeAccessKey,
|
|
665
|
+
selectAccount: capabilities?.selectAccount,
|
|
666
|
+
...(personalSign_request ? { personalSign: personalSign_request } : {}),
|
|
667
|
+
},
|
|
668
|
+
request,
|
|
669
|
+
)
|
|
670
|
+
})()
|
|
661
671
|
|
|
662
672
|
store.setState({
|
|
663
673
|
accounts: resolveAccounts(accounts),
|
|
@@ -713,12 +723,14 @@ export function create(options: create.Options = {}): create.ReturnType {
|
|
|
713
723
|
},
|
|
714
724
|
}
|
|
715
725
|
: {}),
|
|
716
|
-
...(signature && (!auth_request || auth_result)
|
|
726
|
+
...(signature && (!auth_request || auth_result || !verifyUrl)
|
|
717
727
|
? { signature }
|
|
718
728
|
: {}),
|
|
719
729
|
...(email !== undefined ? { email } : {}),
|
|
720
730
|
...(username !== undefined ? { username } : {}),
|
|
721
|
-
...(auth_result
|
|
731
|
+
...((auth_result ?? auth_capability)
|
|
732
|
+
? { auth: auth_result ?? auth_capability }
|
|
733
|
+
: {}),
|
|
722
734
|
...(personalSign
|
|
723
735
|
? { personalSign: { message: personalSign.message } }
|
|
724
736
|
: {}),
|
|
@@ -802,7 +814,7 @@ export function create(options: create.Options = {}): create.ReturnType {
|
|
|
802
814
|
message: '`deposit` not supported by adapter.',
|
|
803
815
|
})
|
|
804
816
|
return (await actions.deposit(
|
|
805
|
-
request._decoded.params[0],
|
|
817
|
+
request._decoded.params?.[0] ?? {},
|
|
806
818
|
request,
|
|
807
819
|
)) satisfies Rpc.wallet_deposit.Encoded['returns']
|
|
808
820
|
}
|
|
@@ -973,15 +985,20 @@ export function create(options: create.Options = {}): create.ReturnType {
|
|
|
973
985
|
),
|
|
974
986
|
{
|
|
975
987
|
chains,
|
|
976
|
-
getAccount
|
|
988
|
+
getAccount() {
|
|
989
|
+
const account = getAccount()
|
|
990
|
+
return { address: account.address, type: 'json-rpc' as const }
|
|
991
|
+
},
|
|
977
992
|
async getAccessKeyStatus(options: getAccessKeyStatus.Options = {}) {
|
|
978
993
|
const state = store.getState()
|
|
979
994
|
const address = options.address ?? state.accounts[state.activeAccount]?.address
|
|
980
|
-
if (!address) return
|
|
995
|
+
if (!address) return 'missing'
|
|
981
996
|
const chainId = options.chainId ?? state.chainId
|
|
997
|
+
const { accessKey, calls } = options
|
|
982
998
|
return await AccessKey.getStatus({
|
|
983
|
-
|
|
984
|
-
|
|
999
|
+
account: address,
|
|
1000
|
+
...(accessKey ? { accessKey } : {}),
|
|
1001
|
+
...(calls ? { calls } : {}),
|
|
985
1002
|
chainId,
|
|
986
1003
|
client: provider.getClient({ chainId }),
|
|
987
1004
|
store,
|
|
@@ -1031,31 +1048,22 @@ export function create(options: create.Options = {}): create.ReturnType {
|
|
|
1031
1048
|
const polyfill = polyfill_option ?? isFetchWritable()
|
|
1032
1049
|
const getClient = ({ chainId }: { chainId?: number | undefined }) => {
|
|
1033
1050
|
const client = provider.getClient({ chainId })
|
|
1034
|
-
const account =
|
|
1035
|
-
|
|
1051
|
+
const account = store.getState().accounts[store.getState().activeAccount]
|
|
1052
|
+
if (!account) throw new ox_Provider.DisconnectedError({ message: 'No active account.' })
|
|
1053
|
+
return Object.assign(client, {
|
|
1054
|
+
account: {
|
|
1055
|
+
address: account.address,
|
|
1056
|
+
type: 'json-rpc' as const,
|
|
1057
|
+
},
|
|
1058
|
+
})
|
|
1036
1059
|
}
|
|
1037
|
-
|
|
1060
|
+
Mppx.create({
|
|
1038
1061
|
methods: [
|
|
1039
1062
|
mppx_tempo({ ...methodOptions, getClient, mode }),
|
|
1040
1063
|
mppx_tempo.subscription({ getClient }),
|
|
1041
1064
|
],
|
|
1042
1065
|
polyfill,
|
|
1043
1066
|
})
|
|
1044
|
-
mppx.onPaymentResponse(({ challenge, method }) => {
|
|
1045
|
-
if (method.name !== 'tempo' || method.intent !== 'charge') return
|
|
1046
|
-
const amount = challenge.request.amount
|
|
1047
|
-
if (
|
|
1048
|
-
typeof amount !== 'string' &&
|
|
1049
|
-
typeof amount !== 'number' &&
|
|
1050
|
-
typeof amount !== 'bigint' &&
|
|
1051
|
-
typeof amount !== 'boolean'
|
|
1052
|
-
)
|
|
1053
|
-
return
|
|
1054
|
-
if (BigInt(amount) === 0n) return
|
|
1055
|
-
const account = provider.getAccount()
|
|
1056
|
-
if ('source' in account && account.source === 'accessKey')
|
|
1057
|
-
AccessKey.removePending(account, { store })
|
|
1058
|
-
})
|
|
1059
1067
|
}
|
|
1060
1068
|
|
|
1061
1069
|
providerRef = provider
|
|
@@ -1132,7 +1140,7 @@ export declare namespace create {
|
|
|
1132
1140
|
* @example
|
|
1133
1141
|
* ```ts
|
|
1134
1142
|
* import { http } from 'viem'
|
|
1135
|
-
* import { tempo, tempoModerato } from 'viem/chains'
|
|
1143
|
+
* import { tempo, tempoModerato } from 'viem/tempo/chains'
|
|
1136
1144
|
*
|
|
1137
1145
|
* const provider = Provider.create({
|
|
1138
1146
|
* transports: {
|
|
@@ -1161,7 +1169,7 @@ export declare namespace getAccessKeyStatus {
|
|
|
1161
1169
|
}
|
|
1162
1170
|
|
|
1163
1171
|
/** Access-key publication status. */
|
|
1164
|
-
type ReturnType =
|
|
1172
|
+
type ReturnType = 'missing' | 'pending' | 'published' | 'expired'
|
|
1165
1173
|
}
|
|
1166
1174
|
|
|
1167
1175
|
export declare namespace mpp {
|
|
@@ -1266,14 +1274,16 @@ function resolveAuthEndpoint(
|
|
|
1266
1274
|
}
|
|
1267
1275
|
|
|
1268
1276
|
/**
|
|
1269
|
-
* Pre-resolves the `auth` capability into its absolute
|
|
1270
|
-
*
|
|
1271
|
-
*
|
|
1272
|
-
*
|
|
1273
|
-
*
|
|
1277
|
+
* Pre-resolves the `auth` capability into its absolute object form. Run
|
|
1278
|
+
* once at the dapp-side Provider so forwarding adapters (dialog) carry
|
|
1279
|
+
* absolute URLs to the wallet host — the wallet's `window.location.origin`
|
|
1280
|
+
* belongs to the wallet, not the dapp, and cannot resolve relative paths
|
|
1281
|
+
* correctly.
|
|
1274
1282
|
*
|
|
1275
|
-
*
|
|
1276
|
-
*
|
|
1283
|
+
* Individual endpoints are omitted when the input doesn't supply enough
|
|
1284
|
+
* info to derive them. `logout` is optional in the protocol; `verify` can
|
|
1285
|
+
* also be omitted by wallet-host re-entry so the dapp-origin Provider runs
|
|
1286
|
+
* verification and receives the session cookie.
|
|
1277
1287
|
*/
|
|
1278
1288
|
function absolutizeAuth(
|
|
1279
1289
|
auth: NonNullable<z.output<typeof Rpc.wallet_connect.auth>>,
|
|
@@ -1297,10 +1307,6 @@ function absolutizeAuth(
|
|
|
1297
1307
|
|
|
1298
1308
|
function assertSameAuthOrigin(auth: NonNullable<z.output<typeof Rpc.wallet_connect.auth>>): void {
|
|
1299
1309
|
if (typeof auth !== 'object') return
|
|
1300
|
-
if (!auth.challenge || !auth.verify)
|
|
1301
|
-
throw new RpcResponse.InvalidParamsError({
|
|
1302
|
-
message: '`auth` requires both `challenge` and `verify` endpoints.',
|
|
1303
|
-
})
|
|
1304
1310
|
const urls = [auth.challenge, auth.verify, auth.logout].filter(
|
|
1305
1311
|
(u): u is string => typeof u === 'string',
|
|
1306
1312
|
)
|
package/src/core/Remote.test.ts
CHANGED
|
@@ -290,3 +290,31 @@ describe('validateSearch', () => {
|
|
|
290
290
|
expect(remote.rejectAll).not.toHaveBeenCalled()
|
|
291
291
|
})
|
|
292
292
|
})
|
|
293
|
+
|
|
294
|
+
describe('respond', () => {
|
|
295
|
+
test('behavior: defer returns the provider result without sending a response', async () => {
|
|
296
|
+
const send = vi.fn()
|
|
297
|
+
const remote = Remote.create({
|
|
298
|
+
messenger: {
|
|
299
|
+
on: vi.fn(),
|
|
300
|
+
ready: vi.fn(),
|
|
301
|
+
send,
|
|
302
|
+
} as never,
|
|
303
|
+
provider: {
|
|
304
|
+
request: vi.fn(async () => ({ ok: true })),
|
|
305
|
+
} as never,
|
|
306
|
+
})
|
|
307
|
+
|
|
308
|
+
const result = await remote.respond(
|
|
309
|
+
{ id: 1, jsonrpc: '2.0', method: 'wallet_connect' } as never,
|
|
310
|
+
{ defer: true },
|
|
311
|
+
)
|
|
312
|
+
|
|
313
|
+
expect(result).toMatchInlineSnapshot(`
|
|
314
|
+
{
|
|
315
|
+
"ok": true,
|
|
316
|
+
}
|
|
317
|
+
`)
|
|
318
|
+
expect(send).not.toHaveBeenCalled()
|
|
319
|
+
})
|
|
320
|
+
})
|
package/src/core/Remote.ts
CHANGED
|
@@ -110,6 +110,8 @@ export declare namespace ready {
|
|
|
110
110
|
|
|
111
111
|
export declare namespace respond {
|
|
112
112
|
type Options = {
|
|
113
|
+
/** Return the resolved result without sending the RPC response. */
|
|
114
|
+
defer?: boolean | undefined
|
|
113
115
|
/** Error to respond with (takes precedence over result). */
|
|
114
116
|
error?: { code: number; message: string } | undefined
|
|
115
117
|
/**
|
|
@@ -237,7 +239,7 @@ export function create(options: create.Options): Remote {
|
|
|
237
239
|
},
|
|
238
240
|
|
|
239
241
|
async respond(request, options = {}) {
|
|
240
|
-
const { error, onError, selector } = options
|
|
242
|
+
const { defer, error, onError, selector } = options
|
|
241
243
|
const shared = { id: request.id, jsonrpc: '2.0' } as const
|
|
242
244
|
|
|
243
245
|
if (error) {
|
|
@@ -254,6 +256,7 @@ export function create(options: create.Options): Remote {
|
|
|
254
256
|
let result =
|
|
255
257
|
'result' in options ? options.result : await provider?.request(request as never)
|
|
256
258
|
if (selector) result = selector(result)
|
|
259
|
+
if (defer) return result
|
|
257
260
|
messenger.send(
|
|
258
261
|
'rpc-response',
|
|
259
262
|
Object.assign(RpcResponse.from({ ...shared, result }), { _request: request }),
|
|
@@ -98,6 +98,29 @@ describe('Encoded', () => {
|
|
|
98
98
|
>()
|
|
99
99
|
})
|
|
100
100
|
|
|
101
|
+
test('wallet_connect: showDeposit', () => {
|
|
102
|
+
type Capabilities = NonNullable<
|
|
103
|
+
NonNullable<Rpc.wallet_connect.Encoded['params']>[number]['capabilities']
|
|
104
|
+
>
|
|
105
|
+
type Register = Extract<Capabilities, { method: 'register' }>
|
|
106
|
+
type Login = Extract<Capabilities, { method?: 'login' | undefined }>
|
|
107
|
+
type ShowDeposit = Register['showDeposit']
|
|
108
|
+
type ShowDepositObject = Exclude<Exclude<ShowDeposit, boolean | undefined>, undefined>
|
|
109
|
+
|
|
110
|
+
expectTypeOf<ShowDeposit>().toMatchTypeOf<
|
|
111
|
+
| boolean
|
|
112
|
+
| {
|
|
113
|
+
amount?: string | undefined
|
|
114
|
+
displayName?: string | undefined
|
|
115
|
+
token?: string | undefined
|
|
116
|
+
}
|
|
117
|
+
| undefined
|
|
118
|
+
>()
|
|
119
|
+
expectTypeOf<Login>().not.toHaveProperty('showDeposit')
|
|
120
|
+
expectTypeOf<ShowDepositObject>().not.toHaveProperty('address')
|
|
121
|
+
expectTypeOf<ShowDepositObject>().not.toHaveProperty('chainId')
|
|
122
|
+
})
|
|
123
|
+
|
|
101
124
|
test('wallet_connect: returns', () => {
|
|
102
125
|
expectTypeOf<Rpc.wallet_connect.Encoded['returns']>().toHaveProperty('accounts')
|
|
103
126
|
expectTypeOf<
|
|
@@ -156,6 +179,24 @@ describe('Encoded', () => {
|
|
|
156
179
|
}>()
|
|
157
180
|
})
|
|
158
181
|
|
|
182
|
+
test('wallet_deposit', () => {
|
|
183
|
+
expectTypeOf<Rpc.wallet_deposit.Encoded>().toMatchTypeOf<{
|
|
184
|
+
method: 'wallet_deposit'
|
|
185
|
+
params:
|
|
186
|
+
| readonly [
|
|
187
|
+
{
|
|
188
|
+
address?: Hex | undefined
|
|
189
|
+
amount?: string | undefined
|
|
190
|
+
chainId?: Hex | undefined
|
|
191
|
+
displayName?: string | undefined
|
|
192
|
+
token?: Hex | string | undefined
|
|
193
|
+
},
|
|
194
|
+
]
|
|
195
|
+
| undefined
|
|
196
|
+
returns: { receipts?: readonly { transactionHash: Hex }[] | undefined } | undefined
|
|
197
|
+
}>()
|
|
198
|
+
})
|
|
199
|
+
|
|
159
200
|
test('wallet_switchEthereumChain', () => {
|
|
160
201
|
expectTypeOf<Rpc.wallet_switchEthereumChain.Encoded>().toEqualTypeOf<{
|
|
161
202
|
method: 'wallet_switchEthereumChain'
|