accounts 0.3.0 → 0.4.1
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 +13 -0
- package/LICENSE +21 -0
- package/README.md +97 -0
- package/dist/core/AccessKey.d.ts +55 -0
- package/dist/core/AccessKey.d.ts.map +1 -0
- package/dist/core/AccessKey.js +69 -0
- package/dist/core/AccessKey.js.map +1 -0
- package/dist/core/Account.d.ts +91 -0
- package/dist/core/Account.d.ts.map +1 -0
- package/dist/core/Account.js +64 -0
- package/dist/core/Account.js.map +1 -0
- package/dist/core/Adapter.d.ts +187 -0
- package/dist/core/Adapter.d.ts.map +1 -0
- package/dist/core/Adapter.js +7 -0
- package/dist/core/Adapter.js.map +1 -0
- package/dist/core/Ceremony.d.ts +109 -0
- package/dist/core/Ceremony.d.ts.map +1 -0
- package/dist/core/Ceremony.js +104 -0
- package/dist/core/Ceremony.js.map +1 -0
- package/dist/core/Client.d.ts +16 -0
- package/dist/core/Client.d.ts.map +1 -0
- package/dist/core/Client.js +18 -0
- package/dist/core/Client.js.map +1 -0
- package/dist/core/Dialog.d.ts +52 -0
- package/dist/core/Dialog.d.ts.map +1 -0
- package/dist/core/Dialog.js +342 -0
- package/dist/core/Dialog.js.map +1 -0
- package/dist/core/Expiry.d.ts +15 -0
- package/dist/core/Expiry.d.ts.map +1 -0
- package/dist/core/Expiry.js +29 -0
- package/dist/core/Expiry.js.map +1 -0
- package/dist/core/Messenger.d.ts +86 -0
- package/dist/core/Messenger.d.ts.map +1 -0
- package/dist/core/Messenger.js +127 -0
- package/dist/core/Messenger.js.map +1 -0
- package/dist/core/Provider.d.ts +69 -0
- package/dist/core/Provider.d.ts.map +1 -0
- package/dist/core/Provider.js +401 -0
- package/dist/core/Provider.js.map +1 -0
- package/dist/core/Remote.d.ts +114 -0
- package/dist/core/Remote.d.ts.map +1 -0
- package/dist/core/Remote.js +116 -0
- package/dist/core/Remote.js.map +1 -0
- package/dist/core/Schema.d.ts +805 -0
- package/dist/core/Schema.d.ts.map +1 -0
- package/dist/core/Schema.js +43 -0
- package/dist/core/Schema.js.map +1 -0
- package/dist/core/Storage.d.ts +42 -0
- package/dist/core/Storage.d.ts.map +1 -0
- package/dist/core/Storage.js +173 -0
- package/dist/core/Storage.js.map +1 -0
- package/dist/core/Store.d.ts +58 -0
- package/dist/core/Store.d.ts.map +1 -0
- package/dist/core/Store.js +58 -0
- package/dist/core/Store.js.map +1 -0
- package/dist/core/adapters/dangerous_secp256k1.d.ts +30 -0
- package/dist/core/adapters/dangerous_secp256k1.d.ts.map +1 -0
- package/dist/core/adapters/dangerous_secp256k1.js +39 -0
- package/dist/core/adapters/dangerous_secp256k1.js.map +1 -0
- package/dist/core/adapters/dialog.d.ts +31 -0
- package/dist/core/adapters/dialog.d.ts.map +1 -0
- package/dist/core/adapters/dialog.js +306 -0
- package/dist/core/adapters/dialog.js.map +1 -0
- package/dist/core/adapters/local.d.ts +33 -0
- package/dist/core/adapters/local.d.ts.map +1 -0
- package/dist/core/adapters/local.js +227 -0
- package/dist/core/adapters/local.js.map +1 -0
- package/dist/core/adapters/webAuthn.d.ts +36 -0
- package/dist/core/adapters/webAuthn.d.ts.map +1 -0
- package/dist/core/adapters/webAuthn.js +93 -0
- package/dist/core/adapters/webAuthn.js.map +1 -0
- package/dist/core/internal/withDedupe.d.ts +12 -0
- package/dist/core/internal/withDedupe.d.ts.map +1 -0
- package/dist/core/internal/withDedupe.js +12 -0
- package/dist/core/internal/withDedupe.js.map +1 -0
- package/dist/core/zod/request.d.ts +31 -0
- package/dist/core/zod/request.d.ts.map +1 -0
- package/dist/core/zod/request.js +41 -0
- package/dist/core/zod/request.js.map +1 -0
- package/dist/core/zod/rpc.d.ts +603 -0
- package/dist/core/zod/rpc.d.ts.map +1 -0
- package/dist/core/zod/rpc.js +293 -0
- package/dist/core/zod/rpc.js.map +1 -0
- package/dist/core/zod/utils.d.ts +18 -0
- package/dist/core/zod/utils.d.ts.map +1 -0
- package/dist/core/zod/utils.js +21 -0
- package/dist/core/zod/utils.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/types.d.ts +284 -0
- package/dist/internal/types.d.ts.map +1 -0
- package/dist/internal/types.js +2 -0
- package/dist/internal/types.js.map +1 -0
- package/dist/server/Handler.d.ts +257 -0
- package/dist/server/Handler.d.ts.map +1 -0
- package/dist/server/Handler.js +433 -0
- package/dist/server/Handler.js.map +1 -0
- package/dist/server/Kv.d.ts +16 -0
- package/dist/server/Kv.d.ts.map +1 -0
- package/dist/server/Kv.js +30 -0
- package/dist/server/Kv.js.map +1 -0
- package/dist/server/index.d.ts +3 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +3 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/internal/requestListener.d.ts +124 -0
- package/dist/server/internal/requestListener.d.ts.map +1 -0
- package/dist/server/internal/requestListener.js +173 -0
- package/dist/server/internal/requestListener.js.map +1 -0
- package/dist/wagmi/Connector.d.ts +93 -0
- package/dist/wagmi/Connector.d.ts.map +1 -0
- package/dist/wagmi/Connector.js +238 -0
- package/dist/wagmi/Connector.js.map +1 -0
- package/dist/wagmi/index.d.ts +3 -0
- package/dist/wagmi/index.d.ts.map +1 -0
- package/dist/wagmi/index.js +3 -0
- package/dist/wagmi/index.js.map +1 -0
- package/package.json +56 -2
- package/src/core/AccessKey.test.ts +257 -0
- package/src/core/AccessKey.ts +123 -0
- package/src/core/Account.test.ts +309 -0
- package/src/core/Account.ts +152 -0
- package/src/core/Adapter.ts +238 -0
- package/src/core/Ceremony.browser.test.ts +239 -0
- package/src/core/Ceremony.test.ts +151 -0
- package/src/core/Ceremony.ts +203 -0
- package/src/core/Client.ts +36 -0
- package/src/core/Dialog.browser.test.ts +309 -0
- package/src/core/Dialog.test-d.ts +19 -0
- package/src/core/Dialog.ts +442 -0
- package/src/core/Expiry.ts +34 -0
- package/src/core/Messenger.ts +206 -0
- package/src/core/Provider.browser.test.ts +774 -0
- package/src/core/Provider.connect.browser.test.ts +415 -0
- package/src/core/Provider.test-d.ts +53 -0
- package/src/core/Provider.test.ts +1566 -0
- package/src/core/Provider.ts +559 -0
- package/src/core/Remote.ts +262 -0
- package/src/core/Schema.test-d.ts +211 -0
- package/src/core/Schema.ts +143 -0
- package/src/core/Storage.ts +213 -0
- package/src/core/Store.test.ts +287 -0
- package/src/core/Store.ts +129 -0
- package/src/core/adapters/dangerous_secp256k1.ts +53 -0
- package/src/core/adapters/dialog.ts +379 -0
- package/src/core/adapters/local.test.ts +97 -0
- package/src/core/adapters/local.ts +277 -0
- package/src/core/adapters/webAuthn.ts +129 -0
- package/src/core/internal/withDedupe.test.ts +116 -0
- package/src/core/internal/withDedupe.ts +20 -0
- package/src/core/mppx.test.ts +83 -0
- package/src/core/zod/request.test.ts +121 -0
- package/src/core/zod/request.ts +70 -0
- package/src/core/zod/rpc.ts +374 -0
- package/src/core/zod/utils.test.ts +69 -0
- package/src/core/zod/utils.ts +40 -0
- package/src/index.ts +14 -0
- package/src/internal/types.ts +378 -0
- package/src/server/Handler.test.ts +1014 -0
- package/src/server/Handler.ts +605 -0
- package/src/server/Kv.ts +46 -0
- package/src/server/index.ts +2 -0
- package/src/server/internal/requestListener.ts +273 -0
- package/src/tsconfig.json +9 -0
- package/src/wagmi/Connector.ts +287 -0
- package/src/wagmi/index.ts +2 -0
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
import { Hex } from 'ox'
|
|
2
|
+
import { type Address, createClient, defineChain, parseUnits } from 'viem'
|
|
3
|
+
import { tempoLocalnet, tempoModerato } from 'viem/chains'
|
|
4
|
+
import { Actions, Addresses } from 'viem/tempo'
|
|
5
|
+
import { afterEach, beforeAll, describe, expect, test } from 'vp/test'
|
|
6
|
+
|
|
7
|
+
import { accounts, http } from '../../test/config.js'
|
|
8
|
+
import { interact } from '../../test/utils.browser.js'
|
|
9
|
+
import { dialog } from './adapters/dialog.js'
|
|
10
|
+
import * as Expiry from './Expiry.js'
|
|
11
|
+
import * as Provider from './Provider.js'
|
|
12
|
+
import * as Storage from './Storage.js'
|
|
13
|
+
|
|
14
|
+
const host = 'https://localhost:5175'
|
|
15
|
+
const rpcPort = import.meta.env.VITE_RPC_PORT ?? '8546'
|
|
16
|
+
const rpcUrl = `http://localhost:${rpcPort}/99999`
|
|
17
|
+
|
|
18
|
+
const chain = defineChain({
|
|
19
|
+
...tempoLocalnet,
|
|
20
|
+
rpcUrls: { default: { http: [rpcUrl] } },
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
const client = createClient({ chain, transport: http(rpcUrl), pollingInterval: 100 })
|
|
24
|
+
|
|
25
|
+
beforeAll(async () => {
|
|
26
|
+
await Promise.all(
|
|
27
|
+
[1n, 2n, 3n].map((tokenId) =>
|
|
28
|
+
Actions.amm.mintSync(client, {
|
|
29
|
+
account: accounts[0]!,
|
|
30
|
+
feeToken: Addresses.pathUsd,
|
|
31
|
+
nonceKey: 'expiring',
|
|
32
|
+
userTokenAddress: tokenId,
|
|
33
|
+
validatorTokenAddress: Addresses.pathUsd,
|
|
34
|
+
validatorTokenAmount: parseUnits('1000', 6),
|
|
35
|
+
to: accounts[0]!.address,
|
|
36
|
+
}),
|
|
37
|
+
),
|
|
38
|
+
)
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
const transferCall = Actions.token.transfer.call({
|
|
42
|
+
to: '0x0000000000000000000000000000000000000001',
|
|
43
|
+
token: Addresses.pathUsd,
|
|
44
|
+
amount: parseUnits('1', 6),
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
function getProvider(options: Partial<Provider.create.Options> = {}) {
|
|
48
|
+
return Provider.create({
|
|
49
|
+
adapter: dialog({ host }),
|
|
50
|
+
chains: [chain],
|
|
51
|
+
storage: Storage.idb({ key: crypto.randomUUID() }),
|
|
52
|
+
...options,
|
|
53
|
+
})
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
let provider: Provider.Provider | undefined
|
|
57
|
+
|
|
58
|
+
afterEach(() => {
|
|
59
|
+
if (provider) {
|
|
60
|
+
provider.store.setState(provider.store.getInitialState())
|
|
61
|
+
window.localStorage.clear()
|
|
62
|
+
window.sessionStorage.clear()
|
|
63
|
+
}
|
|
64
|
+
document.querySelectorAll('dialog[data-tempo-wallet]').forEach((el) => el.remove())
|
|
65
|
+
provider = undefined
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
/** Register via iframe and return the account address. */
|
|
69
|
+
async function connectViaIframe(p: Provider.Provider) {
|
|
70
|
+
const result = await interact(
|
|
71
|
+
p.request({
|
|
72
|
+
method: 'wallet_connect',
|
|
73
|
+
params: [{ capabilities: { method: 'register' } }],
|
|
74
|
+
}),
|
|
75
|
+
async (iframe) => {
|
|
76
|
+
await iframe.getByTestId('confirm').click()
|
|
77
|
+
},
|
|
78
|
+
)
|
|
79
|
+
return result.accounts[0]!.address
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** Fund an address with PathUSD from the pre-funded test account. */
|
|
83
|
+
async function fund(address: Address) {
|
|
84
|
+
await Actions.token.transferSync(client, {
|
|
85
|
+
account: accounts[0]!,
|
|
86
|
+
feeToken: Addresses.pathUsd,
|
|
87
|
+
to: address,
|
|
88
|
+
token: Addresses.pathUsd,
|
|
89
|
+
amount: parseUnits('10', 6),
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
describe('wallet_connect', () => {
|
|
94
|
+
test('default: register via iframe confirm', async () => {
|
|
95
|
+
provider = getProvider()
|
|
96
|
+
|
|
97
|
+
const result = await interact(
|
|
98
|
+
provider.request({
|
|
99
|
+
method: 'wallet_connect',
|
|
100
|
+
params: [{ capabilities: { method: 'register' } }],
|
|
101
|
+
}),
|
|
102
|
+
async (iframe) => {
|
|
103
|
+
await iframe.getByTestId('confirm').click()
|
|
104
|
+
},
|
|
105
|
+
)
|
|
106
|
+
expect(result.accounts.length).toBeGreaterThanOrEqual(1)
|
|
107
|
+
expect(result.accounts[0]!.address).toMatch(/^0x[0-9a-fA-F]{40}$/)
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
test('behavior: reject via iframe', async () => {
|
|
111
|
+
provider = getProvider()
|
|
112
|
+
|
|
113
|
+
await expect(
|
|
114
|
+
interact(
|
|
115
|
+
provider.request({
|
|
116
|
+
method: 'wallet_connect',
|
|
117
|
+
params: [{ capabilities: { method: 'register' } }],
|
|
118
|
+
}),
|
|
119
|
+
async (iframe) => {
|
|
120
|
+
await iframe.getByTestId('reject').click()
|
|
121
|
+
},
|
|
122
|
+
),
|
|
123
|
+
).rejects.toThrow()
|
|
124
|
+
})
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
describe('wallet_disconnect', () => {
|
|
128
|
+
test('default: clears state after connect', async () => {
|
|
129
|
+
provider = getProvider()
|
|
130
|
+
await connectViaIframe(provider)
|
|
131
|
+
|
|
132
|
+
await provider.request({ method: 'wallet_disconnect' })
|
|
133
|
+
expect(provider.store.getState().accounts).toHaveLength(0)
|
|
134
|
+
})
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
describe('eth_accounts', () => {
|
|
138
|
+
test('default: returns accounts after connect', async () => {
|
|
139
|
+
provider = getProvider()
|
|
140
|
+
await connectViaIframe(provider)
|
|
141
|
+
|
|
142
|
+
const result = await provider.request({ method: 'eth_accounts' })
|
|
143
|
+
expect(result.length).toBeGreaterThanOrEqual(1)
|
|
144
|
+
})
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
describe('eth_chainId', () => {
|
|
148
|
+
test('default: returns chain ID', async () => {
|
|
149
|
+
provider = getProvider()
|
|
150
|
+
|
|
151
|
+
const chainId = await provider.request({ method: 'eth_chainId' })
|
|
152
|
+
expect(chainId).toBeDefined()
|
|
153
|
+
})
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
describe('eth_sendTransaction', () => {
|
|
157
|
+
test('default: sends transaction via iframe confirm and returns hash', async () => {
|
|
158
|
+
provider = getProvider()
|
|
159
|
+
const address = await connectViaIframe(provider)
|
|
160
|
+
await fund(address)
|
|
161
|
+
|
|
162
|
+
const hash = await interact(
|
|
163
|
+
provider.request({
|
|
164
|
+
method: 'eth_sendTransaction',
|
|
165
|
+
params: [{ calls: [transferCall] }],
|
|
166
|
+
}),
|
|
167
|
+
async (iframe) => {
|
|
168
|
+
await iframe.getByTestId('confirm').click()
|
|
169
|
+
},
|
|
170
|
+
)
|
|
171
|
+
expect(hash).toMatch(/^0x[0-9a-f]{64}$/)
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
test('behavior: reject via iframe', async () => {
|
|
175
|
+
provider = getProvider()
|
|
176
|
+
await connectViaIframe(provider)
|
|
177
|
+
|
|
178
|
+
await expect(
|
|
179
|
+
interact(
|
|
180
|
+
provider.request({
|
|
181
|
+
method: 'eth_sendTransaction',
|
|
182
|
+
params: [{ calls: [transferCall] }],
|
|
183
|
+
}),
|
|
184
|
+
async (iframe) => {
|
|
185
|
+
await iframe.getByTestId('reject').click()
|
|
186
|
+
},
|
|
187
|
+
),
|
|
188
|
+
).rejects.toThrow()
|
|
189
|
+
})
|
|
190
|
+
})
|
|
191
|
+
|
|
192
|
+
describe('eth_sendTransactionSync', () => {
|
|
193
|
+
test('default: sends transaction via iframe confirm and returns receipt', async () => {
|
|
194
|
+
provider = getProvider()
|
|
195
|
+
const address = await connectViaIframe(provider)
|
|
196
|
+
await fund(address)
|
|
197
|
+
|
|
198
|
+
const receipt = await interact(
|
|
199
|
+
provider.request({
|
|
200
|
+
method: 'eth_sendTransactionSync',
|
|
201
|
+
params: [{ calls: [transferCall] }],
|
|
202
|
+
}),
|
|
203
|
+
async (iframe) => {
|
|
204
|
+
await iframe.getByTestId('confirm').click()
|
|
205
|
+
},
|
|
206
|
+
)
|
|
207
|
+
expect(receipt.status).toMatchInlineSnapshot(`"0x1"`)
|
|
208
|
+
expect(receipt.transactionHash).toMatch(/^0x[0-9a-f]{64}$/)
|
|
209
|
+
})
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
describe('eth_signTransaction', () => {
|
|
213
|
+
test('default: signs transaction via iframe confirm and returns serialized', async () => {
|
|
214
|
+
provider = getProvider()
|
|
215
|
+
const address = await connectViaIframe(provider)
|
|
216
|
+
await fund(address)
|
|
217
|
+
|
|
218
|
+
const signed = await interact(
|
|
219
|
+
provider.request({
|
|
220
|
+
method: 'eth_signTransaction',
|
|
221
|
+
params: [{ calls: [transferCall] }],
|
|
222
|
+
}),
|
|
223
|
+
async (iframe) => {
|
|
224
|
+
await iframe.getByTestId('confirm').click()
|
|
225
|
+
},
|
|
226
|
+
)
|
|
227
|
+
expect(signed).toMatch(/^0x/)
|
|
228
|
+
})
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
describe('personal_sign', () => {
|
|
232
|
+
test('default: signs message via iframe confirm', async () => {
|
|
233
|
+
provider = getProvider()
|
|
234
|
+
const address = await connectViaIframe(provider)
|
|
235
|
+
|
|
236
|
+
const message = Hex.fromString('hello world')
|
|
237
|
+
const signature = await interact(
|
|
238
|
+
provider.request({
|
|
239
|
+
method: 'personal_sign',
|
|
240
|
+
params: [message, address],
|
|
241
|
+
}),
|
|
242
|
+
async (iframe) => {
|
|
243
|
+
await iframe.getByTestId('confirm').click()
|
|
244
|
+
},
|
|
245
|
+
)
|
|
246
|
+
expect(signature).toMatch(/^0x[0-9a-f]+$/)
|
|
247
|
+
})
|
|
248
|
+
|
|
249
|
+
test('behavior: reject via iframe', async () => {
|
|
250
|
+
provider = getProvider()
|
|
251
|
+
const address = await connectViaIframe(provider)
|
|
252
|
+
|
|
253
|
+
const message = Hex.fromString('hello world')
|
|
254
|
+
await expect(
|
|
255
|
+
interact(
|
|
256
|
+
provider.request({
|
|
257
|
+
method: 'personal_sign',
|
|
258
|
+
params: [message, address],
|
|
259
|
+
}),
|
|
260
|
+
async (iframe) => {
|
|
261
|
+
await iframe.getByTestId('reject').click()
|
|
262
|
+
},
|
|
263
|
+
),
|
|
264
|
+
).rejects.toThrow()
|
|
265
|
+
})
|
|
266
|
+
})
|
|
267
|
+
|
|
268
|
+
describe('eth_signTypedData_v4', () => {
|
|
269
|
+
const typedData = {
|
|
270
|
+
domain: { name: 'Test', version: '1', chainId: 1 },
|
|
271
|
+
types: {
|
|
272
|
+
Person: [
|
|
273
|
+
{ name: 'name', type: 'string' },
|
|
274
|
+
{ name: 'wallet', type: 'address' },
|
|
275
|
+
],
|
|
276
|
+
},
|
|
277
|
+
primaryType: 'Person' as const,
|
|
278
|
+
message: { name: 'Bob', wallet: '0x0000000000000000000000000000000000000000' },
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
test('default: signs typed data via iframe confirm', async () => {
|
|
282
|
+
provider = getProvider()
|
|
283
|
+
const address = await connectViaIframe(provider)
|
|
284
|
+
|
|
285
|
+
const signature = await interact(
|
|
286
|
+
provider.request({
|
|
287
|
+
method: 'eth_signTypedData_v4',
|
|
288
|
+
params: [address, JSON.stringify(typedData)],
|
|
289
|
+
}),
|
|
290
|
+
async (iframe) => {
|
|
291
|
+
await iframe.getByTestId('confirm').click()
|
|
292
|
+
},
|
|
293
|
+
)
|
|
294
|
+
expect(signature).toMatch(/^0x[0-9a-f]+$/)
|
|
295
|
+
})
|
|
296
|
+
})
|
|
297
|
+
|
|
298
|
+
describe('wallet_authorizeAccessKey', () => {
|
|
299
|
+
test('default: authorizes access key via iframe confirm', async () => {
|
|
300
|
+
provider = getProvider()
|
|
301
|
+
await connectViaIframe(provider)
|
|
302
|
+
|
|
303
|
+
const result = await interact(
|
|
304
|
+
provider.request({
|
|
305
|
+
method: 'wallet_authorizeAccessKey',
|
|
306
|
+
params: [{ expiry: Expiry.days(1) }],
|
|
307
|
+
}),
|
|
308
|
+
async (iframe) => {
|
|
309
|
+
await iframe.getByTestId('confirm').click()
|
|
310
|
+
},
|
|
311
|
+
)
|
|
312
|
+
expect(result.address).toMatch(/^0x[0-9a-fA-F]{40}$/)
|
|
313
|
+
})
|
|
314
|
+
})
|
|
315
|
+
|
|
316
|
+
describe('wallet_revokeAccessKey', () => {
|
|
317
|
+
test('default: revokes access key via iframe confirm', async () => {
|
|
318
|
+
provider = getProvider()
|
|
319
|
+
const address = await connectViaIframe(provider)
|
|
320
|
+
|
|
321
|
+
const { address: keyAddress } = await interact(
|
|
322
|
+
provider.request({
|
|
323
|
+
method: 'wallet_authorizeAccessKey',
|
|
324
|
+
params: [{ expiry: Expiry.days(1) }],
|
|
325
|
+
}),
|
|
326
|
+
async (iframe) => {
|
|
327
|
+
await iframe.getByTestId('confirm').click()
|
|
328
|
+
},
|
|
329
|
+
)
|
|
330
|
+
|
|
331
|
+
await interact(
|
|
332
|
+
provider.request({
|
|
333
|
+
method: 'wallet_revokeAccessKey',
|
|
334
|
+
params: [{ address, accessKeyAddress: keyAddress }],
|
|
335
|
+
}),
|
|
336
|
+
async (iframe) => {
|
|
337
|
+
await iframe.getByTestId('confirm').click()
|
|
338
|
+
},
|
|
339
|
+
)
|
|
340
|
+
})
|
|
341
|
+
})
|
|
342
|
+
|
|
343
|
+
describe('wallet_switchEthereumChain', () => {
|
|
344
|
+
test('default: switches chain', async () => {
|
|
345
|
+
provider = getProvider({ chains: [chain, tempoModerato] })
|
|
346
|
+
|
|
347
|
+
await provider.request({
|
|
348
|
+
method: 'wallet_switchEthereumChain',
|
|
349
|
+
params: [{ chainId: `0x${tempoModerato.id.toString(16)}` }],
|
|
350
|
+
})
|
|
351
|
+
|
|
352
|
+
const chainId = await provider.request({ method: 'eth_chainId' })
|
|
353
|
+
expect(chainId).toMatchInlineSnapshot(`"0xa5bf"`)
|
|
354
|
+
})
|
|
355
|
+
|
|
356
|
+
test('error: throws for unconfigured chain', async () => {
|
|
357
|
+
provider = getProvider()
|
|
358
|
+
|
|
359
|
+
await expect(
|
|
360
|
+
provider.request({
|
|
361
|
+
method: 'wallet_switchEthereumChain',
|
|
362
|
+
params: [{ chainId: '0x1' }],
|
|
363
|
+
}),
|
|
364
|
+
).rejects.toThrow()
|
|
365
|
+
})
|
|
366
|
+
})
|
|
367
|
+
|
|
368
|
+
describe('edge cases', () => {
|
|
369
|
+
test('behavior: dialog backdrop click rejects pending request', async () => {
|
|
370
|
+
provider = getProvider()
|
|
371
|
+
await connectViaIframe(provider)
|
|
372
|
+
|
|
373
|
+
await expect(
|
|
374
|
+
interact(
|
|
375
|
+
provider.request({
|
|
376
|
+
method: 'personal_sign',
|
|
377
|
+
params: [Hex.fromString('hello'), provider.store.getState().accounts[0]!.address],
|
|
378
|
+
}),
|
|
379
|
+
async () => {
|
|
380
|
+
const dialog = document.querySelector('dialog[data-tempo-wallet]') as HTMLDialogElement
|
|
381
|
+
dialog.dispatchEvent(new Event('cancel'))
|
|
382
|
+
},
|
|
383
|
+
),
|
|
384
|
+
).rejects.toThrow()
|
|
385
|
+
})
|
|
386
|
+
|
|
387
|
+
test('behavior: sequential requests each get confirmed', async () => {
|
|
388
|
+
provider = getProvider()
|
|
389
|
+
const address = await connectViaIframe(provider)
|
|
390
|
+
await fund(address)
|
|
391
|
+
|
|
392
|
+
const hash1 = await interact(
|
|
393
|
+
provider.request({
|
|
394
|
+
method: 'eth_sendTransaction',
|
|
395
|
+
params: [{ calls: [transferCall] }],
|
|
396
|
+
}),
|
|
397
|
+
async (iframe) => {
|
|
398
|
+
await iframe.getByTestId('confirm').click()
|
|
399
|
+
},
|
|
400
|
+
)
|
|
401
|
+
expect(hash1).toMatch(/^0x[0-9a-f]{64}$/)
|
|
402
|
+
|
|
403
|
+
const hash2 = await interact(
|
|
404
|
+
provider.request({
|
|
405
|
+
method: 'eth_sendTransaction',
|
|
406
|
+
params: [{ calls: [transferCall] }],
|
|
407
|
+
}),
|
|
408
|
+
async (iframe) => {
|
|
409
|
+
await iframe.getByTestId('confirm').click()
|
|
410
|
+
},
|
|
411
|
+
)
|
|
412
|
+
expect(hash2).toMatch(/^0x[0-9a-f]{64}$/)
|
|
413
|
+
expect(hash1).not.toBe(hash2)
|
|
414
|
+
})
|
|
415
|
+
})
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { RpcSchema } from 'ox'
|
|
2
|
+
import { describe, expectTypeOf, test } from 'vp/test'
|
|
3
|
+
|
|
4
|
+
import type * as Schema from './Schema.js'
|
|
5
|
+
|
|
6
|
+
type Result<method extends RpcSchema.MethodNameGeneric<Schema.Ox>> = RpcSchema.ExtractReturnType<
|
|
7
|
+
Schema.Ox,
|
|
8
|
+
method
|
|
9
|
+
>
|
|
10
|
+
|
|
11
|
+
describe('request', () => {
|
|
12
|
+
test('eth_accounts', () => {
|
|
13
|
+
expectTypeOf<Result<'eth_accounts'>>().toEqualTypeOf<readonly `0x${string}`[]>()
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
test('eth_chainId', () => {
|
|
17
|
+
expectTypeOf<Result<'eth_chainId'>>().toEqualTypeOf<`0x${string}`>()
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
test('eth_requestAccounts', () => {
|
|
21
|
+
expectTypeOf<Result<'eth_requestAccounts'>>().toEqualTypeOf<readonly `0x${string}`[]>()
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
test('eth_sendTransaction', () => {
|
|
25
|
+
expectTypeOf<Result<'eth_sendTransaction'>>().toEqualTypeOf<`0x${string}`>()
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
test('wallet_connect', () => {
|
|
29
|
+
expectTypeOf<Result<'wallet_connect'>>().toMatchTypeOf<{
|
|
30
|
+
accounts: readonly {
|
|
31
|
+
address: `0x${string}`
|
|
32
|
+
capabilities: {
|
|
33
|
+
accessKey?:
|
|
34
|
+
| {
|
|
35
|
+
address: `0x${string}`
|
|
36
|
+
expiry?: number | undefined
|
|
37
|
+
limits?: { token: `0x${string}`; limit: string }[] | undefined
|
|
38
|
+
}
|
|
39
|
+
| undefined
|
|
40
|
+
signature?: `0x${string}` | undefined
|
|
41
|
+
}
|
|
42
|
+
}[]
|
|
43
|
+
}>()
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
test('wallet_disconnect', () => {
|
|
47
|
+
expectTypeOf<Result<'wallet_disconnect'>>().toEqualTypeOf<undefined>()
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
test('wallet_switchEthereumChain', () => {
|
|
51
|
+
expectTypeOf<Result<'wallet_switchEthereumChain'>>().toEqualTypeOf<undefined>()
|
|
52
|
+
})
|
|
53
|
+
})
|