tempo.ts 0.7.6 → 0.8.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 +32 -0
- package/dist/chains.d.ts +6 -20
- package/dist/chains.d.ts.map +1 -1
- package/dist/chains.js +14 -15
- package/dist/chains.js.map +1 -1
- package/dist/ox/KeyAuthorization.d.ts +356 -0
- package/dist/ox/KeyAuthorization.d.ts.map +1 -0
- package/dist/ox/KeyAuthorization.js +360 -0
- package/dist/ox/KeyAuthorization.js.map +1 -0
- package/dist/ox/SignatureEnvelope.d.ts +21 -6
- package/dist/ox/SignatureEnvelope.d.ts.map +1 -1
- package/dist/ox/SignatureEnvelope.js +43 -3
- package/dist/ox/SignatureEnvelope.js.map +1 -1
- package/dist/ox/Transaction.d.ts +5 -1
- package/dist/ox/Transaction.d.ts.map +1 -1
- package/dist/ox/Transaction.js +5 -0
- package/dist/ox/Transaction.js.map +1 -1
- package/dist/ox/TransactionEnvelopeAA.d.ts +9 -0
- package/dist/ox/TransactionEnvelopeAA.d.ts.map +1 -1
- package/dist/ox/TransactionEnvelopeAA.js +17 -4
- package/dist/ox/TransactionEnvelopeAA.js.map +1 -1
- package/dist/ox/TransactionRequest.d.ts +7 -1
- package/dist/ox/TransactionRequest.d.ts.map +1 -1
- package/dist/ox/TransactionRequest.js +12 -0
- package/dist/ox/TransactionRequest.js.map +1 -1
- package/dist/ox/index.d.ts +1 -0
- package/dist/ox/index.d.ts.map +1 -1
- package/dist/ox/index.js +1 -0
- package/dist/ox/index.js.map +1 -1
- package/dist/prool/Instance.js +1 -1
- package/dist/prool/Instance.js.map +1 -1
- package/{src/prool/internal → dist/prool}/chain.json +4 -2
- package/dist/viem/Abis.d.ts +319 -6
- package/dist/viem/Abis.d.ts.map +1 -1
- package/dist/viem/Abis.js +199 -7
- package/dist/viem/Abis.js.map +1 -1
- package/dist/viem/Account.d.ts +103 -14
- package/dist/viem/Account.d.ts.map +1 -1
- package/dist/viem/Account.js +177 -23
- package/dist/viem/Account.js.map +1 -1
- package/dist/viem/Actions/account.d.ts.map +1 -1
- package/dist/viem/Actions/account.js +4 -5
- package/dist/viem/Actions/account.js.map +1 -1
- package/dist/viem/Actions/amm.d.ts +72 -0
- package/dist/viem/Actions/amm.d.ts.map +1 -1
- package/dist/viem/Actions/dex.d.ts +156 -4
- package/dist/viem/Actions/dex.d.ts.map +1 -1
- package/dist/viem/Actions/fee.d.ts +4 -0
- package/dist/viem/Actions/fee.d.ts.map +1 -1
- package/dist/viem/Actions/reward.d.ts +158 -0
- package/dist/viem/Actions/reward.d.ts.map +1 -1
- package/dist/viem/Actions/reward.js +54 -0
- package/dist/viem/Actions/reward.js.map +1 -1
- package/dist/viem/Actions/token.d.ts +585 -0
- package/dist/viem/Actions/token.d.ts.map +1 -1
- package/dist/viem/Actions/token.js +2 -2
- package/dist/viem/Actions/token.js.map +1 -1
- package/dist/viem/Addresses.d.ts +1 -1
- package/dist/viem/Addresses.d.ts.map +1 -1
- package/dist/viem/Addresses.js +1 -1
- package/dist/viem/Addresses.js.map +1 -1
- package/dist/viem/Chain.d.ts +35 -0
- package/dist/viem/Chain.d.ts.map +1 -1
- package/dist/viem/Chain.js +37 -0
- package/dist/viem/Chain.js.map +1 -1
- package/dist/viem/Decorator.d.ts +74 -0
- package/dist/viem/Decorator.d.ts.map +1 -1
- package/dist/viem/Decorator.js +3 -0
- package/dist/viem/Decorator.js.map +1 -1
- package/dist/viem/Formatters.d.ts.map +1 -1
- package/dist/viem/Formatters.js +8 -7
- package/dist/viem/Formatters.js.map +1 -1
- package/dist/viem/Storage.d.ts +1 -0
- package/dist/viem/Storage.d.ts.map +1 -1
- package/dist/viem/Storage.js +21 -0
- package/dist/viem/Storage.js.map +1 -1
- package/dist/viem/TokenIds.d.ts +1 -1
- package/dist/viem/TokenIds.d.ts.map +1 -1
- package/dist/viem/TokenIds.js +1 -1
- package/dist/viem/TokenIds.js.map +1 -1
- package/dist/viem/Transaction.d.ts +9 -1
- package/dist/viem/Transaction.d.ts.map +1 -1
- package/dist/viem/Transaction.js +2 -1
- package/dist/viem/Transaction.js.map +1 -1
- package/dist/viem/WebAuthnP256.d.ts +4 -1
- package/dist/viem/WebAuthnP256.d.ts.map +1 -1
- package/dist/viem/WebAuthnP256.js +3 -1
- package/dist/viem/WebAuthnP256.js.map +1 -1
- package/dist/wagmi/Actions/reward.d.ts +44 -0
- package/dist/wagmi/Actions/reward.d.ts.map +1 -1
- package/dist/wagmi/Actions/reward.js +49 -0
- package/dist/wagmi/Actions/reward.js.map +1 -1
- package/dist/wagmi/Connector.d.ts +25 -8
- package/dist/wagmi/Connector.d.ts.map +1 -1
- package/dist/wagmi/Connector.js +120 -27
- package/dist/wagmi/Connector.js.map +1 -1
- package/dist/wagmi/Hooks/reward.d.ts +32 -0
- package/dist/wagmi/Hooks/reward.d.ts.map +1 -1
- package/dist/wagmi/Hooks/reward.js +39 -0
- package/dist/wagmi/Hooks/reward.js.map +1 -1
- package/package.json +3 -2
- package/src/chains.ts +14 -15
- package/src/ox/KeyAuthorization.test.ts +1332 -0
- package/src/ox/KeyAuthorization.ts +542 -0
- package/src/ox/SignatureEnvelope.test.ts +624 -0
- package/src/ox/SignatureEnvelope.ts +89 -9
- package/src/ox/Transaction.test.ts +214 -0
- package/src/ox/Transaction.ts +13 -1
- package/src/ox/TransactionEnvelopeAA.test.ts +164 -4
- package/src/ox/TransactionEnvelopeAA.ts +36 -3
- package/src/ox/TransactionRequest.ts +22 -1
- package/src/ox/e2e.test.ts +612 -5
- package/src/ox/index.ts +1 -0
- package/src/prool/Instance.ts +1 -1
- package/src/prool/chain.json +238 -0
- package/src/server/Handler.test.ts +20 -36
- package/src/viem/Abis.ts +200 -7
- package/src/viem/Account.test.ts +444 -0
- package/src/viem/Account.ts +355 -42
- package/src/viem/Actions/account.ts +3 -5
- package/src/viem/Actions/amm.test.ts +4 -4
- package/src/viem/Actions/reward.test.ts +84 -0
- package/src/viem/Actions/reward.ts +73 -0
- package/src/viem/Actions/token.test.ts +8 -8
- package/src/viem/Actions/token.ts +2 -2
- package/src/viem/Addresses.ts +1 -1
- package/src/viem/Chain.test.ts +168 -0
- package/src/viem/Chain.ts +37 -1
- package/src/viem/Decorator.ts +84 -0
- package/src/viem/Formatters.ts +8 -7
- package/src/viem/Storage.ts +22 -0
- package/src/viem/TokenIds.ts +1 -1
- package/src/viem/Transaction.ts +14 -2
- package/src/viem/WebAuthnP256.ts +8 -2
- package/src/viem/e2e.test.ts +299 -96
- package/src/wagmi/Actions/amm.test.ts +2 -2
- package/src/wagmi/Actions/reward.test.ts +36 -0
- package/src/wagmi/Actions/reward.ts +91 -0
- package/src/wagmi/Connector.test.ts +1 -1
- package/src/wagmi/Connector.ts +184 -54
- package/src/wagmi/Hooks/amm.test.ts +4 -4
- package/src/wagmi/Hooks/fee.test.ts +10 -4
- package/src/wagmi/Hooks/reward.test.ts +72 -0
- package/src/wagmi/Hooks/reward.ts +68 -0
- package/src/wagmi/Hooks/token.test.ts +0 -488
- package/dist/viem/internal/account.d.ts +0 -21
- package/dist/viem/internal/account.d.ts.map +0 -1
- package/dist/viem/internal/account.js +0 -61
- package/dist/viem/internal/account.js.map +0 -1
- package/src/viem/internal/account.ts +0 -89
|
@@ -116,7 +116,7 @@ describe('mintSync', () => {
|
|
|
116
116
|
})
|
|
117
117
|
})
|
|
118
118
|
|
|
119
|
-
describe('burnSync', () => {
|
|
119
|
+
describe.skip('burnSync', () => {
|
|
120
120
|
test('default', async () => {
|
|
121
121
|
await connect(config, {
|
|
122
122
|
connector: config.connectors[0]!,
|
|
@@ -167,7 +167,7 @@ describe('burnSync', () => {
|
|
|
167
167
|
})
|
|
168
168
|
})
|
|
169
169
|
|
|
170
|
-
describe('rebalanceSwapSync', () => {
|
|
170
|
+
describe.skip('rebalanceSwapSync', () => {
|
|
171
171
|
test('default', async () => {
|
|
172
172
|
await connect(config, {
|
|
173
173
|
connector: config.connectors[0]!,
|
|
@@ -89,6 +89,42 @@ describe('getTotalPerSecond', () => {
|
|
|
89
89
|
})
|
|
90
90
|
})
|
|
91
91
|
|
|
92
|
+
describe('getUserRewardInfo', () => {
|
|
93
|
+
test('default', async () => {
|
|
94
|
+
const { token } = await setupToken()
|
|
95
|
+
|
|
96
|
+
const account = getAccount(config)
|
|
97
|
+
|
|
98
|
+
const info = await actions.getUserRewardInfo(config, {
|
|
99
|
+
token,
|
|
100
|
+
account: account.address!,
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
expect(info.rewardRecipient).toBeDefined()
|
|
104
|
+
expect(info.rewardPerToken).toBeDefined()
|
|
105
|
+
expect(info.rewardBalance).toBeDefined()
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
describe('queryOptions', () => {
|
|
109
|
+
test('default', async () => {
|
|
110
|
+
const { token } = await setupToken()
|
|
111
|
+
|
|
112
|
+
const account = getAccount(config)
|
|
113
|
+
|
|
114
|
+
const options = actions.getUserRewardInfo.queryOptions(config, {
|
|
115
|
+
token,
|
|
116
|
+
account: account.address!,
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
const info = await queryClient.fetchQuery(options)
|
|
120
|
+
|
|
121
|
+
expect(info.rewardRecipient).toBeDefined()
|
|
122
|
+
expect(info.rewardPerToken).toBeDefined()
|
|
123
|
+
expect(info.rewardBalance).toBeDefined()
|
|
124
|
+
})
|
|
125
|
+
})
|
|
126
|
+
})
|
|
127
|
+
|
|
92
128
|
describe('setRecipientSync', () => {
|
|
93
129
|
test('default', async () => {
|
|
94
130
|
const { token } = await setupToken()
|
|
@@ -205,6 +205,97 @@ export namespace getTotalPerSecond {
|
|
|
205
205
|
}
|
|
206
206
|
}
|
|
207
207
|
|
|
208
|
+
/**
|
|
209
|
+
* Gets the reward information for a specific account.
|
|
210
|
+
*
|
|
211
|
+
* @example
|
|
212
|
+
* ```ts
|
|
213
|
+
* import { createConfig, http } from '@wagmi/core'
|
|
214
|
+
* import { tempo } from 'tempo.ts/chains'
|
|
215
|
+
* import { Actions } from 'tempo.ts/wagmi'
|
|
216
|
+
*
|
|
217
|
+
* const config = createConfig({
|
|
218
|
+
* chains: [tempo({ feeToken: '0x20c0000000000000000000000000000000000001' })],
|
|
219
|
+
* transports: {
|
|
220
|
+
* [tempo.id]: http(),
|
|
221
|
+
* },
|
|
222
|
+
* })
|
|
223
|
+
*
|
|
224
|
+
* const info = await Actions.reward.getUserRewardInfo(config, {
|
|
225
|
+
* token: '0x20c0000000000000000000000000000000000001',
|
|
226
|
+
* account: '0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC',
|
|
227
|
+
* })
|
|
228
|
+
* ```
|
|
229
|
+
*
|
|
230
|
+
* @param config - Config.
|
|
231
|
+
* @param parameters - Parameters.
|
|
232
|
+
* @returns The user's reward information (recipient, rewardPerToken, rewardBalance).
|
|
233
|
+
*/
|
|
234
|
+
export function getUserRewardInfo<config extends Config>(
|
|
235
|
+
config: config,
|
|
236
|
+
parameters: getUserRewardInfo.Parameters<config>,
|
|
237
|
+
) {
|
|
238
|
+
const { chainId, ...rest } = parameters
|
|
239
|
+
const client = config.getClient({ chainId })
|
|
240
|
+
return viem_Actions.getUserRewardInfo(client, rest)
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
export namespace getUserRewardInfo {
|
|
244
|
+
export type Parameters<config extends Config> = ChainIdParameter<config> &
|
|
245
|
+
viem_Actions.getUserRewardInfo.Parameters
|
|
246
|
+
|
|
247
|
+
export type ReturnValue = viem_Actions.getUserRewardInfo.ReturnValue
|
|
248
|
+
|
|
249
|
+
export function queryKey<config extends Config>(
|
|
250
|
+
parameters: Parameters<config>,
|
|
251
|
+
) {
|
|
252
|
+
return ['getUserRewardInfo', parameters] as const
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
export type QueryKey<config extends Config> = ReturnType<
|
|
256
|
+
typeof queryKey<config>
|
|
257
|
+
>
|
|
258
|
+
|
|
259
|
+
export function queryOptions<config extends Config, selectData = ReturnValue>(
|
|
260
|
+
config: Config,
|
|
261
|
+
parameters: queryOptions.Parameters<config, selectData>,
|
|
262
|
+
): queryOptions.ReturnValue<config, selectData> {
|
|
263
|
+
const { query, ...rest } = parameters
|
|
264
|
+
return {
|
|
265
|
+
...query,
|
|
266
|
+
queryKey: queryKey(rest),
|
|
267
|
+
async queryFn({ queryKey }) {
|
|
268
|
+
const [, parameters] = queryKey
|
|
269
|
+
return await getUserRewardInfo(config, parameters)
|
|
270
|
+
},
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
export declare namespace queryOptions {
|
|
275
|
+
export type Parameters<
|
|
276
|
+
config extends Config,
|
|
277
|
+
selectData = getUserRewardInfo.ReturnValue,
|
|
278
|
+
> = getUserRewardInfo.Parameters<config> & {
|
|
279
|
+
query?:
|
|
280
|
+
| Omit<ReturnValue<config, selectData>, 'queryKey' | 'queryFn'>
|
|
281
|
+
| undefined
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
export type ReturnValue<
|
|
285
|
+
config extends Config,
|
|
286
|
+
selectData = getUserRewardInfo.ReturnValue,
|
|
287
|
+
> = RequiredBy<
|
|
288
|
+
Query.QueryOptions<
|
|
289
|
+
getUserRewardInfo.ReturnValue,
|
|
290
|
+
Query.DefaultError,
|
|
291
|
+
selectData,
|
|
292
|
+
getUserRewardInfo.QueryKey<config>
|
|
293
|
+
>,
|
|
294
|
+
'queryKey' | 'queryFn'
|
|
295
|
+
>
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
208
299
|
/**
|
|
209
300
|
* Sets or changes the reward recipient for a token holder.
|
|
210
301
|
*
|
|
@@ -40,10 +40,10 @@ test('connect', async (context) => {
|
|
|
40
40
|
expect(result.current.useAccount.status).toEqual('disconnected')
|
|
41
41
|
|
|
42
42
|
result.current.useConnect.connect({
|
|
43
|
+
capabilities: { type: 'sign-up', label: 'Test Account' },
|
|
43
44
|
connector: webAuthn({
|
|
44
45
|
keyManager: KeyManager.localStorage(),
|
|
45
46
|
}),
|
|
46
|
-
capabilities: { createAccount: { label: 'Test Account' } },
|
|
47
47
|
})
|
|
48
48
|
|
|
49
49
|
await vi.waitFor(() =>
|
package/src/wagmi/Connector.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as Address from 'ox/Address'
|
|
2
2
|
import type * as Hex from 'ox/Hex'
|
|
3
|
+
import * as PublicKey from 'ox/PublicKey'
|
|
3
4
|
import {
|
|
4
5
|
createClient,
|
|
5
6
|
type EIP1193Provider,
|
|
@@ -9,11 +10,16 @@ import {
|
|
|
9
10
|
} from 'viem'
|
|
10
11
|
import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'
|
|
11
12
|
import { ChainNotConfiguredError, createConnector } from 'wagmi'
|
|
13
|
+
import type { OneOf } from '../internal/types.js'
|
|
14
|
+
import * as KeyAuthorization from '../ox/KeyAuthorization.js'
|
|
15
|
+
import * as SignatureEnvelope from '../ox/SignatureEnvelope.js'
|
|
12
16
|
import * as Account from '../viem/Account.js'
|
|
13
17
|
import type * as tempo_Chain from '../viem/Chain.js'
|
|
14
18
|
import { normalizeValue } from '../viem/internal/utils.js'
|
|
19
|
+
import * as Storage from '../viem/Storage.js'
|
|
15
20
|
import { walletNamespaceCompat } from '../viem/Transport.js'
|
|
16
21
|
import * as WebAuthnP256 from '../viem/WebAuthnP256.js'
|
|
22
|
+
import * as WebCryptoP256 from '../viem/WebCryptoP256.js'
|
|
17
23
|
import type * as KeyManager from './KeyManager.js'
|
|
18
24
|
|
|
19
25
|
type Chain = ReturnType<ReturnType<typeof tempo_Chain.define>>
|
|
@@ -35,9 +41,12 @@ export function dangerous_secp256k1(
|
|
|
35
41
|
type Properties = {
|
|
36
42
|
connect<withCapabilities extends boolean = false>(parameters: {
|
|
37
43
|
capabilities?:
|
|
38
|
-
|
|
|
39
|
-
|
|
40
|
-
|
|
44
|
+
| OneOf<
|
|
45
|
+
| {
|
|
46
|
+
type: 'sign-up'
|
|
47
|
+
}
|
|
48
|
+
| {}
|
|
49
|
+
>
|
|
41
50
|
| undefined
|
|
42
51
|
chainId?: number | undefined
|
|
43
52
|
isReconnecting?: boolean | undefined
|
|
@@ -75,7 +84,7 @@ export function dangerous_secp256k1(
|
|
|
75
84
|
const address = await (async () => {
|
|
76
85
|
if (
|
|
77
86
|
'capabilities' in parameters &&
|
|
78
|
-
parameters.capabilities?.
|
|
87
|
+
parameters.capabilities?.type === 'sign-up'
|
|
79
88
|
) {
|
|
80
89
|
const privateKey = generatePrivateKey()
|
|
81
90
|
const account = privateKeyToAccount(privateKey)
|
|
@@ -197,20 +206,28 @@ export declare namespace dangerous_secp256k1 {
|
|
|
197
206
|
* @returns Connector.
|
|
198
207
|
*/
|
|
199
208
|
export function webAuthn(options: webAuthn.Parameters) {
|
|
200
|
-
let account: Account.
|
|
209
|
+
let account: Account.RootAccount | undefined
|
|
210
|
+
let accessKey: Account.AccessKeyAccount | undefined
|
|
211
|
+
|
|
212
|
+
const idbStorage = Storage.idb<{
|
|
213
|
+
[key: `accessKey:${string}`]: WebCryptoP256.createKeyPair.ReturnType
|
|
214
|
+
}>()
|
|
201
215
|
|
|
202
216
|
type Properties = {
|
|
203
217
|
connect<withCapabilities extends boolean = false>(parameters: {
|
|
204
218
|
chainId?: number | undefined
|
|
205
219
|
capabilities?:
|
|
206
|
-
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
220
|
+
| OneOf<
|
|
221
|
+
| {
|
|
222
|
+
label?: string | undefined
|
|
223
|
+
type: 'sign-up'
|
|
224
|
+
}
|
|
225
|
+
| {
|
|
226
|
+
selectAccount?: boolean | undefined
|
|
227
|
+
type: 'sign-in'
|
|
228
|
+
}
|
|
229
|
+
| {}
|
|
230
|
+
>
|
|
214
231
|
| undefined
|
|
215
232
|
isReconnecting?: boolean | undefined
|
|
216
233
|
withCapabilities?: withCapabilities | boolean | undefined
|
|
@@ -234,50 +251,107 @@ export function webAuthn(options: webAuthn.Parameters) {
|
|
|
234
251
|
account = Account.fromWebAuthnP256(credential)
|
|
235
252
|
},
|
|
236
253
|
async connect(parameters = {}) {
|
|
237
|
-
|
|
238
|
-
|
|
254
|
+
const { grantAccessKey = false } = options
|
|
255
|
+
const capabilities =
|
|
256
|
+
'capabilities' in parameters ? (parameters.capabilities ?? {}) : {}
|
|
239
257
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
258
|
+
// We are going to need to find:
|
|
259
|
+
// - a WebAuthn `credential` to instantiate an account
|
|
260
|
+
// - optionally, a `keyPair` to use as the access key for the account
|
|
261
|
+
// - optionally, a signed `keyAuthorization` to provision the access key
|
|
262
|
+
const { credential, keyAuthorization, keyPair } = await (async () => {
|
|
263
|
+
// If the connection type is of "sign-up", we are going to create a new credential
|
|
264
|
+
// and provision an access key (if needed).
|
|
265
|
+
if (capabilities.type === 'sign-up') {
|
|
244
266
|
// Create credential (sign up)
|
|
245
|
-
const createOptions =
|
|
246
|
-
typeof parameters.capabilities?.createAccount === 'boolean'
|
|
247
|
-
? {}
|
|
248
|
-
: parameters.capabilities?.createAccount
|
|
249
267
|
const createOptions_remote = await options.keyManager.getChallenge?.()
|
|
250
|
-
|
|
268
|
+
const label =
|
|
269
|
+
capabilities.label ??
|
|
270
|
+
options.createOptions?.label ??
|
|
271
|
+
new Date().toISOString()
|
|
272
|
+
const rpId =
|
|
273
|
+
createOptions_remote?.rp?.id ??
|
|
274
|
+
options.createOptions?.rpId ??
|
|
275
|
+
options.rpId
|
|
276
|
+
const credential = await WebAuthnP256.createCredential({
|
|
251
277
|
...(options.createOptions ?? {}),
|
|
252
|
-
label
|
|
253
|
-
|
|
254
|
-
options.createOptions?.label ??
|
|
255
|
-
`Account ${new Date().toISOString().split('T')[0]}`,
|
|
256
|
-
rpId:
|
|
257
|
-
createOptions_remote?.rp?.id ??
|
|
258
|
-
options.createOptions?.rpId ??
|
|
259
|
-
options.rpId,
|
|
278
|
+
label,
|
|
279
|
+
rpId,
|
|
260
280
|
...(createOptions_remote ?? {}),
|
|
261
281
|
})
|
|
262
282
|
await options.keyManager.setPublicKey({
|
|
263
283
|
credential: credential.raw,
|
|
264
284
|
publicKey: credential.publicKey,
|
|
265
285
|
})
|
|
266
|
-
|
|
267
|
-
//
|
|
268
|
-
|
|
286
|
+
|
|
287
|
+
// Get key pair (access key) to use for the account.
|
|
288
|
+
const keyPair = await (async () => {
|
|
289
|
+
if (!grantAccessKey) return undefined
|
|
290
|
+
return await WebCryptoP256.createKeyPair()
|
|
291
|
+
})()
|
|
292
|
+
|
|
293
|
+
return { credential, keyPair }
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// If we are not selecting an account, we will check if an active credential is present in
|
|
297
|
+
// storage and if so, we will use it to instantiate an account.
|
|
298
|
+
if (!capabilities.selectAccount) {
|
|
299
|
+
const credential = (await config.storage?.getItem(
|
|
269
300
|
'webAuthn.activeCredential',
|
|
270
|
-
)) as WebAuthnP256.
|
|
301
|
+
)) as WebAuthnP256.getCredential.ReturnValue | undefined
|
|
271
302
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
303
|
+
if (credential) {
|
|
304
|
+
// Get key pair (access key) to use for the account.
|
|
305
|
+
const keyPair = await (async () => {
|
|
306
|
+
if (!grantAccessKey) return undefined
|
|
307
|
+
const address = Address.fromPublicKey(
|
|
308
|
+
PublicKey.fromHex(credential.publicKey),
|
|
309
|
+
)
|
|
310
|
+
return await idbStorage.getItem(`accessKey:${address}`)
|
|
311
|
+
})()
|
|
312
|
+
|
|
313
|
+
// If the access key policy is lax, return the credential and key pair (if exists).
|
|
314
|
+
if (grantAccessKey === 'lax') return { credential, keyPair }
|
|
315
|
+
|
|
316
|
+
// If a key pair is found, return the credential and key pair.
|
|
317
|
+
if (keyPair) return { credential, keyPair }
|
|
318
|
+
|
|
319
|
+
// If we are reconnecting, throw an error if not found.
|
|
320
|
+
if (parameters.isReconnecting)
|
|
321
|
+
throw new Error('credential not found.')
|
|
322
|
+
|
|
323
|
+
// Otherwise, we want to continue to sign up or register against new key pair.
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// Discover credential
|
|
328
|
+
{
|
|
329
|
+
// Get key pair (access key) to use for the account.
|
|
330
|
+
const keyPair = await (async () => {
|
|
331
|
+
if (!grantAccessKey) return undefined
|
|
332
|
+
return await WebCryptoP256.createKeyPair()
|
|
333
|
+
})()
|
|
334
|
+
|
|
335
|
+
// If we are provisioning an access key, we will need to sign a key authorization.
|
|
336
|
+
// We will need the hash (digest) to sign, and the address of the access key to construct the key authorization.
|
|
337
|
+
const { accessKeyAddress, hash } = await (async () => {
|
|
338
|
+
if (!keyPair)
|
|
339
|
+
return { accessKeyAddress: undefined, hash: undefined }
|
|
340
|
+
const accessKeyAddress = Address.fromPublicKey(keyPair.publicKey)
|
|
341
|
+
const hash = KeyAuthorization.getSignPayload({
|
|
342
|
+
address: accessKeyAddress,
|
|
343
|
+
type: 'p256',
|
|
344
|
+
})
|
|
345
|
+
return { accessKeyAddress, hash, keyPair }
|
|
346
|
+
})()
|
|
347
|
+
|
|
348
|
+
// If no active credential, we will attempt to load the last active credential from storage.
|
|
349
|
+
const lastActiveCredential = !capabilities.selectAccount
|
|
350
|
+
? await config.storage?.getItem('webAuthn.lastActiveCredential')
|
|
351
|
+
: undefined
|
|
352
|
+
const credential = await WebAuthnP256.getCredential({
|
|
277
353
|
...(options.getOptions ?? {}),
|
|
278
354
|
credentialId: lastActiveCredential?.id,
|
|
279
|
-
// biome-ignore lint/suspicious/noTsIgnore: _
|
|
280
|
-
// @ts-ignore
|
|
281
355
|
async getPublicKey(credential) {
|
|
282
356
|
const publicKey = await options.keyManager.getPublicKey({
|
|
283
357
|
credential,
|
|
@@ -285,21 +359,63 @@ export function webAuthn(options: webAuthn.Parameters) {
|
|
|
285
359
|
if (!publicKey) throw new Error('publicKey not found.')
|
|
286
360
|
return publicKey
|
|
287
361
|
},
|
|
362
|
+
hash,
|
|
288
363
|
rpId: options.getOptions?.rpId ?? options.rpId,
|
|
289
364
|
})
|
|
290
|
-
}
|
|
291
365
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
366
|
+
const keyAuthorization = accessKeyAddress
|
|
367
|
+
? KeyAuthorization.from({
|
|
368
|
+
address: accessKeyAddress,
|
|
369
|
+
signature: SignatureEnvelope.from({
|
|
370
|
+
metadata: credential.metadata,
|
|
371
|
+
signature: credential.signature,
|
|
372
|
+
publicKey: PublicKey.fromHex(credential.publicKey),
|
|
373
|
+
type: 'webAuthn',
|
|
374
|
+
}),
|
|
375
|
+
type: 'p256',
|
|
376
|
+
})
|
|
377
|
+
: undefined
|
|
378
|
+
|
|
379
|
+
return { credential, keyAuthorization, keyPair }
|
|
380
|
+
}
|
|
301
381
|
})()
|
|
302
382
|
|
|
383
|
+
config.storage?.setItem(
|
|
384
|
+
'webAuthn.lastActiveCredential',
|
|
385
|
+
normalizeValue(credential),
|
|
386
|
+
)
|
|
387
|
+
config.storage?.setItem(
|
|
388
|
+
'webAuthn.activeCredential',
|
|
389
|
+
normalizeValue(credential),
|
|
390
|
+
)
|
|
391
|
+
|
|
392
|
+
account = Account.fromWebAuthnP256(credential, {
|
|
393
|
+
storage: Storage.from(config.storage as never),
|
|
394
|
+
})
|
|
395
|
+
|
|
396
|
+
if (keyPair) {
|
|
397
|
+
accessKey = Account.fromWebCryptoP256(keyPair, {
|
|
398
|
+
access: account,
|
|
399
|
+
storage: Storage.from(config.storage as never),
|
|
400
|
+
})
|
|
401
|
+
|
|
402
|
+
// If we are not reconnecting, orchestrate the provisioning of the access key.
|
|
403
|
+
if (!parameters.isReconnecting) {
|
|
404
|
+
const keyAuth =
|
|
405
|
+
keyAuthorization ?? (await account.signKeyAuthorization(accessKey))
|
|
406
|
+
|
|
407
|
+
await account.storage.setItem('pendingKeyAuthorization', keyAuth)
|
|
408
|
+
await idbStorage.setItem(
|
|
409
|
+
`accessKey:${account.address.toLowerCase()}`,
|
|
410
|
+
keyPair,
|
|
411
|
+
)
|
|
412
|
+
}
|
|
413
|
+
// If we are granting an access key, throw an error if the access key is not provisioned.
|
|
414
|
+
} else if (grantAccessKey === true) {
|
|
415
|
+
await config.storage?.removeItem('webAuthn.activeCredential')
|
|
416
|
+
throw new Error('access key not found')
|
|
417
|
+
}
|
|
418
|
+
|
|
303
419
|
const address = getAddress(account.address)
|
|
304
420
|
|
|
305
421
|
const chainId = parameters.chainId ?? config.chains[0]?.id
|
|
@@ -361,7 +477,7 @@ export function webAuthn(options: webAuthn.Parameters) {
|
|
|
361
477
|
if (!transport) throw new ChainNotConfiguredError()
|
|
362
478
|
|
|
363
479
|
return createClient({
|
|
364
|
-
account,
|
|
480
|
+
account: accessKey ?? account,
|
|
365
481
|
chain: chain as Chain,
|
|
366
482
|
transport: walletNamespaceCompat(transport),
|
|
367
483
|
})
|
|
@@ -386,6 +502,20 @@ export namespace webAuthn {
|
|
|
386
502
|
getOptions?:
|
|
387
503
|
| Pick<WebAuthnP256.getCredential.Parameters, 'getFn' | 'rpId'>
|
|
388
504
|
| undefined
|
|
505
|
+
/**
|
|
506
|
+
* Whether or not to grant an access key upon connection.
|
|
507
|
+
*
|
|
508
|
+
* - `true`: The account MUST have an access key provisioned.
|
|
509
|
+
* On failure, the connection will fail.
|
|
510
|
+
* - `"lax"`: The account MAY have an access key provisioned.
|
|
511
|
+
* On failure, the connection will succeed, but the access key will not be provisioned
|
|
512
|
+
* and must be provisioned manually if the user wants to enforce access keys.
|
|
513
|
+
* - `false`: The account WILL NOT have an access key provisioned. The access key must be
|
|
514
|
+
* provisioned manually if the user wants to enforce access keys.
|
|
515
|
+
*
|
|
516
|
+
* @default false
|
|
517
|
+
*/
|
|
518
|
+
grantAccessKey?: boolean | 'lax'
|
|
389
519
|
/** Public key manager. */
|
|
390
520
|
keyManager: KeyManager.KeyManager
|
|
391
521
|
/** The RP ID to use for WebAuthn. */
|
|
@@ -165,7 +165,7 @@ describe('useMintSync', () => {
|
|
|
165
165
|
})
|
|
166
166
|
})
|
|
167
167
|
|
|
168
|
-
describe('useBurnSync', () => {
|
|
168
|
+
describe.skip('useBurnSync', () => {
|
|
169
169
|
test('default', async () => {
|
|
170
170
|
const { result } = await renderHook(() => ({
|
|
171
171
|
connect: useConnect(),
|
|
@@ -249,7 +249,7 @@ describe('useBurnSync', () => {
|
|
|
249
249
|
})
|
|
250
250
|
})
|
|
251
251
|
|
|
252
|
-
describe('useRebalanceSwapSync', () => {
|
|
252
|
+
describe.skip('useRebalanceSwapSync', () => {
|
|
253
253
|
test('default', async () => {
|
|
254
254
|
const { result } = await renderHook(() => ({
|
|
255
255
|
connect: useConnect(),
|
|
@@ -322,7 +322,7 @@ describe('useRebalanceSwapSync', () => {
|
|
|
322
322
|
})
|
|
323
323
|
})
|
|
324
324
|
|
|
325
|
-
describe('useWatchRebalanceSwap', () => {
|
|
325
|
+
describe.skip('useWatchRebalanceSwap', () => {
|
|
326
326
|
test('default', async () => {
|
|
327
327
|
const { result: connectResult } = await renderHook(() => ({
|
|
328
328
|
connect: useConnect(),
|
|
@@ -468,7 +468,7 @@ describe('useWatchMint', () => {
|
|
|
468
468
|
})
|
|
469
469
|
})
|
|
470
470
|
|
|
471
|
-
describe('useWatchBurn', () => {
|
|
471
|
+
describe.skip('useWatchBurn', () => {
|
|
472
472
|
test('default', async () => {
|
|
473
473
|
const { result: connectResult } = await renderHook(() => ({
|
|
474
474
|
connect: useConnect(),
|
|
@@ -100,15 +100,21 @@ describe('useUserToken', () => {
|
|
|
100
100
|
{
|
|
101
101
|
"account": {
|
|
102
102
|
"address": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
|
|
103
|
-
"
|
|
104
|
-
"
|
|
105
|
-
"publicKey": "
|
|
103
|
+
"assignKeyAuthorization": [Function],
|
|
104
|
+
"keyType": "secp256k1",
|
|
105
|
+
"publicKey": "0x8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed753547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5",
|
|
106
106
|
"sign": [Function],
|
|
107
107
|
"signAuthorization": [Function],
|
|
108
|
+
"signKeyAuthorization": [Function],
|
|
108
109
|
"signMessage": [Function],
|
|
109
110
|
"signTransaction": [Function],
|
|
110
111
|
"signTypedData": [Function],
|
|
111
|
-
"source": "
|
|
112
|
+
"source": "root",
|
|
113
|
+
"storage": {
|
|
114
|
+
"getItem": [Function],
|
|
115
|
+
"removeItem": [Function],
|
|
116
|
+
"setItem": [Function],
|
|
117
|
+
},
|
|
112
118
|
"type": "local",
|
|
113
119
|
},
|
|
114
120
|
"chainId": 1337,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getAccount } from '@wagmi/core'
|
|
1
2
|
import type { Address } from 'viem'
|
|
2
3
|
import { describe, expect, test, vi } from 'vitest'
|
|
3
4
|
import { useConnect } from 'wagmi'
|
|
@@ -53,6 +54,77 @@ describe('useGetTotalPerSecond', () => {
|
|
|
53
54
|
})
|
|
54
55
|
})
|
|
55
56
|
|
|
57
|
+
describe('useUserRewardInfo', () => {
|
|
58
|
+
test('default', async () => {
|
|
59
|
+
const { token } = await setupToken()
|
|
60
|
+
|
|
61
|
+
const account = getAccount(config).address
|
|
62
|
+
|
|
63
|
+
const { result } = await renderHook(() =>
|
|
64
|
+
hooks.useUserRewardInfo({
|
|
65
|
+
token,
|
|
66
|
+
account,
|
|
67
|
+
}),
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
await vi.waitFor(() => expect(result.current.isSuccess).toBeTruthy())
|
|
71
|
+
|
|
72
|
+
expect(result.current.data?.rewardRecipient).toBeDefined()
|
|
73
|
+
expect(result.current.data?.rewardPerToken).toBeDefined()
|
|
74
|
+
expect(result.current.data?.rewardBalance).toBeDefined()
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
test('reactivity: account and token parameters', async () => {
|
|
78
|
+
const { result, rerender } = await renderHook(
|
|
79
|
+
(props) =>
|
|
80
|
+
hooks.useUserRewardInfo({
|
|
81
|
+
token: props?.token,
|
|
82
|
+
account: props?.account,
|
|
83
|
+
}),
|
|
84
|
+
{
|
|
85
|
+
initialProps: {
|
|
86
|
+
token: undefined as Address | undefined,
|
|
87
|
+
account: undefined as Address | undefined,
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
await vi.waitFor(() => result.current.fetchStatus === 'idle')
|
|
93
|
+
|
|
94
|
+
// Should be disabled when both token and account are undefined
|
|
95
|
+
expect(result.current.data).toBeUndefined()
|
|
96
|
+
expect(result.current.isPending).toBe(true)
|
|
97
|
+
expect(result.current.isEnabled).toBe(false)
|
|
98
|
+
|
|
99
|
+
// Setup token (this also connects the account)
|
|
100
|
+
const { token } = await setupToken()
|
|
101
|
+
|
|
102
|
+
// Set token only (account still undefined)
|
|
103
|
+
rerender({ token, account: undefined })
|
|
104
|
+
|
|
105
|
+
await vi.waitFor(() => result.current.fetchStatus === 'idle')
|
|
106
|
+
|
|
107
|
+
// Should still be disabled when account is undefined
|
|
108
|
+
expect(result.current.data).toBeUndefined()
|
|
109
|
+
expect(result.current.isPending).toBe(true)
|
|
110
|
+
expect(result.current.isEnabled).toBe(false)
|
|
111
|
+
|
|
112
|
+
// Get account from config (already connected by setupToken)
|
|
113
|
+
const account = getAccount(config).address
|
|
114
|
+
|
|
115
|
+
// Set both token and account
|
|
116
|
+
rerender({ token, account })
|
|
117
|
+
|
|
118
|
+
await vi.waitFor(() => expect(result.current.isSuccess).toBeTruthy())
|
|
119
|
+
|
|
120
|
+
// Should now be enabled and have data
|
|
121
|
+
expect(result.current.isEnabled).toBe(true)
|
|
122
|
+
expect(result.current.data?.rewardRecipient).toBeDefined()
|
|
123
|
+
expect(result.current.data?.rewardPerToken).toBeDefined()
|
|
124
|
+
expect(result.current.data?.rewardBalance).toBeDefined()
|
|
125
|
+
})
|
|
126
|
+
})
|
|
127
|
+
|
|
56
128
|
describe('useSetRecipientSync', () => {
|
|
57
129
|
test('default', async () => {
|
|
58
130
|
const { result } = await renderHook(() => ({
|