viem 2.54.1 → 2.54.3
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 +30 -0
- package/_cjs/account-abstraction/actions/bundler/estimateUserOperationGas.js +1 -2
- package/_cjs/account-abstraction/actions/bundler/estimateUserOperationGas.js.map +1 -1
- package/_cjs/chains/definitions/marsCredit.js +23 -0
- package/_cjs/chains/definitions/marsCredit.js.map +1 -0
- package/_cjs/chains/index.js +10 -8
- package/_cjs/chains/index.js.map +1 -1
- package/_cjs/clients/createClient.js +1 -0
- package/_cjs/clients/createClient.js.map +1 -1
- package/_cjs/errors/encoding.js +13 -1
- package/_cjs/errors/encoding.js.map +1 -1
- package/_cjs/errors/version.js +1 -1
- package/_cjs/index.js +8 -6
- package/_cjs/index.js.map +1 -1
- package/_cjs/tempo/Abis.js +49 -1
- package/_cjs/tempo/Abis.js.map +1 -1
- package/_cjs/tempo/Addresses.js +3 -1
- package/_cjs/tempo/Addresses.js.map +1 -1
- package/_cjs/tempo/Decorator.js.map +1 -1
- package/_cjs/tempo/Formatters.js +5 -1
- package/_cjs/tempo/Formatters.js.map +1 -1
- package/_cjs/tempo/Selectors.js +8 -1
- package/_cjs/tempo/Selectors.js.map +1 -1
- package/_cjs/tempo/Transaction.js.map +1 -1
- package/_cjs/tempo/actions/receivePolicy.js +29 -5
- package/_cjs/tempo/actions/receivePolicy.js.map +1 -1
- package/_cjs/tempo/actions/virtualAddress.js +2 -5
- package/_cjs/tempo/actions/virtualAddress.js.map +1 -1
- package/_cjs/tempo/actions/zone.js +69 -48
- package/_cjs/tempo/actions/zone.js.map +1 -1
- package/_cjs/tempo/chainConfig.js +11 -2
- package/_cjs/tempo/chainConfig.js.map +1 -1
- package/_cjs/utils/abi/decodeAbiParameters.js +11 -2
- package/_cjs/utils/abi/decodeAbiParameters.js.map +1 -1
- package/_cjs/utils/abi/encodeAbiParameters.js +26 -11
- package/_cjs/utils/abi/encodeAbiParameters.js.map +1 -1
- package/_cjs/utils/encoding/fromRlp.js +9 -0
- package/_cjs/utils/encoding/fromRlp.js.map +1 -1
- package/_esm/account-abstraction/actions/bundler/estimateUserOperationGas.js +1 -2
- package/_esm/account-abstraction/actions/bundler/estimateUserOperationGas.js.map +1 -1
- package/_esm/chains/definitions/marsCredit.js +20 -0
- package/_esm/chains/definitions/marsCredit.js.map +1 -0
- package/_esm/chains/index.js +1 -0
- package/_esm/chains/index.js.map +1 -1
- package/_esm/clients/createClient.js +5 -3
- package/_esm/clients/createClient.js.map +1 -1
- package/_esm/errors/encoding.js +10 -0
- package/_esm/errors/encoding.js.map +1 -1
- package/_esm/errors/version.js +1 -1
- package/_esm/index.js +1 -1
- package/_esm/index.js.map +1 -1
- package/_esm/tempo/Abis.js +48 -0
- package/_esm/tempo/Abis.js.map +1 -1
- package/_esm/tempo/Addresses.js +2 -0
- package/_esm/tempo/Addresses.js.map +1 -1
- package/_esm/tempo/Decorator.js.map +1 -1
- package/_esm/tempo/Formatters.js +7 -1
- package/_esm/tempo/Formatters.js.map +1 -1
- package/_esm/tempo/Selectors.js +7 -0
- package/_esm/tempo/Selectors.js.map +1 -1
- package/_esm/tempo/Transaction.js.map +1 -1
- package/_esm/tempo/actions/receivePolicy.js +32 -5
- package/_esm/tempo/actions/receivePolicy.js.map +1 -1
- package/_esm/tempo/actions/virtualAddress.js +2 -6
- package/_esm/tempo/actions/virtualAddress.js.map +1 -1
- package/_esm/tempo/actions/zone.js +96 -49
- package/_esm/tempo/actions/zone.js.map +1 -1
- package/_esm/tempo/chainConfig.js +11 -2
- package/_esm/tempo/chainConfig.js.map +1 -1
- package/_esm/utils/abi/decodeAbiParameters.js +18 -2
- package/_esm/utils/abi/decodeAbiParameters.js.map +1 -1
- package/_esm/utils/abi/encodeAbiParameters.js +30 -12
- package/_esm/utils/abi/encodeAbiParameters.js.map +1 -1
- package/_esm/utils/encoding/fromRlp.js +12 -1
- package/_esm/utils/encoding/fromRlp.js.map +1 -1
- package/_types/account-abstraction/actions/bundler/estimateUserOperationGas.d.ts.map +1 -1
- package/_types/chains/definitions/marsCredit.d.ts +50 -0
- package/_types/chains/definitions/marsCredit.d.ts.map +1 -0
- package/_types/chains/definitions/tempo.d.ts +42 -0
- package/_types/chains/definitions/tempo.d.ts.map +1 -1
- package/_types/chains/definitions/tempoDevnet.d.ts +42 -0
- package/_types/chains/definitions/tempoDevnet.d.ts.map +1 -1
- package/_types/chains/definitions/tempoLocalnet.d.ts +42 -0
- package/_types/chains/definitions/tempoLocalnet.d.ts.map +1 -1
- package/_types/chains/definitions/tempoModerato.d.ts +42 -0
- package/_types/chains/definitions/tempoModerato.d.ts.map +1 -1
- package/_types/chains/index.d.ts +1 -0
- package/_types/chains/index.d.ts.map +1 -1
- package/_types/clients/createClient.d.ts +4 -3
- package/_types/clients/createClient.d.ts.map +1 -1
- package/_types/errors/encoding.d.ts +17 -0
- package/_types/errors/encoding.d.ts.map +1 -1
- package/_types/errors/version.d.ts +1 -1
- package/_types/index.d.ts +1 -1
- package/_types/index.d.ts.map +1 -1
- package/_types/tempo/Abis.d.ts +119 -0
- package/_types/tempo/Abis.d.ts.map +1 -1
- package/_types/tempo/Addresses.d.ts +2 -0
- package/_types/tempo/Addresses.d.ts.map +1 -1
- package/_types/tempo/Decorator.d.ts +4 -0
- package/_types/tempo/Decorator.d.ts.map +1 -1
- package/_types/tempo/Formatters.d.ts.map +1 -1
- package/_types/tempo/Selectors.d.ts +7 -0
- package/_types/tempo/Selectors.d.ts.map +1 -1
- package/_types/tempo/Transaction.d.ts +11 -0
- package/_types/tempo/Transaction.d.ts.map +1 -1
- package/_types/tempo/actions/receivePolicy.d.ts +1 -1
- package/_types/tempo/actions/receivePolicy.d.ts.map +1 -1
- package/_types/tempo/actions/virtualAddress.d.ts.map +1 -1
- package/_types/tempo/actions/zone.d.ts +63 -3
- package/_types/tempo/actions/zone.d.ts.map +1 -1
- package/_types/tempo/chainConfig.d.ts +22 -0
- package/_types/tempo/chainConfig.d.ts.map +1 -1
- package/_types/tempo/zones/zone.d.ts +126 -0
- package/_types/tempo/zones/zone.d.ts.map +1 -1
- package/_types/utils/abi/decodeAbiParameters.d.ts.map +1 -1
- package/_types/utils/abi/encodeAbiParameters.d.ts +5 -5
- package/_types/utils/abi/encodeAbiParameters.d.ts.map +1 -1
- package/_types/utils/encoding/fromRlp.d.ts +3 -3
- package/_types/utils/encoding/fromRlp.d.ts.map +1 -1
- package/account-abstraction/actions/bundler/estimateUserOperationGas.ts +1 -2
- package/chains/definitions/marsCredit.ts +20 -0
- package/chains/index.ts +1 -0
- package/clients/createClient.ts +5 -3
- package/errors/encoding.ts +26 -0
- package/errors/version.ts +1 -1
- package/index.ts +4 -0
- package/package.json +3 -3
- package/tempo/Abis.ts +49 -0
- package/tempo/Addresses.ts +2 -0
- package/tempo/Decorator.ts +3 -0
- package/tempo/Formatters.ts +8 -0
- package/tempo/Selectors.ts +8 -0
- package/tempo/Transaction.ts +10 -0
- package/tempo/actions/receivePolicy.ts +39 -4
- package/tempo/actions/virtualAddress.ts +2 -8
- package/tempo/actions/zone.ts +164 -74
- package/tempo/chainConfig.ts +11 -2
- package/utils/abi/decodeAbiParameters.ts +17 -2
- package/utils/abi/encodeAbiParameters.ts +32 -15
- package/utils/encoding/fromRlp.ts +18 -1
package/tempo/Abis.ts
CHANGED
|
@@ -2570,6 +2570,54 @@ export const validatorConfig = [
|
|
|
2570
2570
|
},
|
|
2571
2571
|
] as const
|
|
2572
2572
|
|
|
2573
|
+
export const storageCredits = [
|
|
2574
|
+
{
|
|
2575
|
+
type: 'error',
|
|
2576
|
+
name: 'DelegateCallNotAllowed',
|
|
2577
|
+
inputs: [],
|
|
2578
|
+
},
|
|
2579
|
+
{
|
|
2580
|
+
type: 'error',
|
|
2581
|
+
name: 'InvalidMode',
|
|
2582
|
+
inputs: [],
|
|
2583
|
+
},
|
|
2584
|
+
{
|
|
2585
|
+
type: 'function',
|
|
2586
|
+
name: 'balanceOf',
|
|
2587
|
+
stateMutability: 'view',
|
|
2588
|
+
inputs: [{ name: 'account', type: 'address' }],
|
|
2589
|
+
outputs: [{ type: 'uint64' }],
|
|
2590
|
+
},
|
|
2591
|
+
{
|
|
2592
|
+
type: 'function',
|
|
2593
|
+
name: 'modeOf',
|
|
2594
|
+
stateMutability: 'view',
|
|
2595
|
+
inputs: [{ name: 'account', type: 'address' }],
|
|
2596
|
+
outputs: [{ type: 'uint8' }],
|
|
2597
|
+
},
|
|
2598
|
+
{
|
|
2599
|
+
type: 'function',
|
|
2600
|
+
name: 'budgetOf',
|
|
2601
|
+
stateMutability: 'view',
|
|
2602
|
+
inputs: [{ name: 'account', type: 'address' }],
|
|
2603
|
+
outputs: [{ type: 'uint64' }],
|
|
2604
|
+
},
|
|
2605
|
+
{
|
|
2606
|
+
type: 'function',
|
|
2607
|
+
name: 'setMode',
|
|
2608
|
+
stateMutability: 'nonpayable',
|
|
2609
|
+
inputs: [{ name: 'newMode', type: 'uint8' }],
|
|
2610
|
+
outputs: [],
|
|
2611
|
+
},
|
|
2612
|
+
{
|
|
2613
|
+
type: 'function',
|
|
2614
|
+
name: 'setBudget',
|
|
2615
|
+
stateMutability: 'nonpayable',
|
|
2616
|
+
inputs: [{ name: 'creditBudget', type: 'uint64' }],
|
|
2617
|
+
outputs: [],
|
|
2618
|
+
},
|
|
2619
|
+
] as const
|
|
2620
|
+
|
|
2573
2621
|
export const validatorConfigV2 = [
|
|
2574
2622
|
{
|
|
2575
2623
|
name: 'getActiveValidators',
|
|
@@ -2931,6 +2979,7 @@ export const abis = [
|
|
|
2931
2979
|
...receivePolicyGuard,
|
|
2932
2980
|
...signatureVerifier,
|
|
2933
2981
|
...stablecoinDex,
|
|
2982
|
+
...storageCredits,
|
|
2934
2983
|
...tip20,
|
|
2935
2984
|
...tip20ChannelReserve,
|
|
2936
2985
|
...tip20Factory,
|
package/tempo/Addresses.ts
CHANGED
|
@@ -9,6 +9,8 @@ export const pathUsd = '0x20c0000000000000000000000000000000000000'
|
|
|
9
9
|
export const receivePolicyGuard = '0xB10C000000000000000000000000000000000000'
|
|
10
10
|
export const signatureVerifier = '0x5165300000000000000000000000000000000000'
|
|
11
11
|
export const stablecoinDex = '0xdec0000000000000000000000000000000000000'
|
|
12
|
+
export const storageCredits = '0x1060000000000000000000000000000000000000'
|
|
13
|
+
export const tip20ChannelReserve = '0x4d50500000000000000000000000000000000000'
|
|
12
14
|
export const tip20Factory = '0x20fc000000000000000000000000000000000000'
|
|
13
15
|
export const tip403Registry = '0x403c000000000000000000000000000000000000'
|
|
14
16
|
export const validator = '0xcccccccc00000000000000000000000000000000'
|
package/tempo/Decorator.ts
CHANGED
|
@@ -5129,6 +5129,9 @@ type BoundActionHelpers<action> = (action extends { call: infer helper }
|
|
|
5129
5129
|
(action extends { estimateGas: infer helper }
|
|
5130
5130
|
? { estimateGas: BoundHelper<helper> }
|
|
5131
5131
|
: {}) &
|
|
5132
|
+
(action extends { prepare: infer helper }
|
|
5133
|
+
? { prepare: BoundHelper<helper> }
|
|
5134
|
+
: {}) &
|
|
5132
5135
|
(action extends { simulate: infer helper }
|
|
5133
5136
|
? { simulate: BoundHelper<helper> }
|
|
5134
5137
|
: {}) &
|
package/tempo/Formatters.ts
CHANGED
|
@@ -121,8 +121,12 @@ export function formatTransactionRequest(
|
|
|
121
121
|
// `multisig` / `signatures` are client-side only (TIP-1061). They drive
|
|
122
122
|
// sender derivation, owner signing, and final envelope assembly, but are
|
|
123
123
|
// never sent as raw RPC fields — the wire payload is the serialized tx.
|
|
124
|
+
// `multisigInit` / `multisigSignatureCount` are wire fields: the node
|
|
125
|
+
// prices multisig gas from them during simulation.
|
|
124
126
|
const {
|
|
125
127
|
multisig: _multisig,
|
|
128
|
+
multisigInit,
|
|
129
|
+
multisigSignatureCount,
|
|
126
130
|
signatures: _signatures,
|
|
127
131
|
...rpcRequest
|
|
128
132
|
} = request
|
|
@@ -164,6 +168,10 @@ export function formatTransactionRequest(
|
|
|
164
168
|
|
|
165
169
|
return {
|
|
166
170
|
...rpc,
|
|
171
|
+
...(multisigInit ? { multisigInit } : {}),
|
|
172
|
+
...(typeof multisigSignatureCount !== 'undefined'
|
|
173
|
+
? { multisigSignatureCount }
|
|
174
|
+
: {}),
|
|
167
175
|
...(request.capabilities ? { capabilities: request.capabilities } : {}),
|
|
168
176
|
...(keyData ? { keyData } : {}),
|
|
169
177
|
...(keyId ? { keyId } : {}),
|
package/tempo/Selectors.ts
CHANGED
|
@@ -94,6 +94,14 @@ export const stablecoinDex = {
|
|
|
94
94
|
withdraw: '0x08fab167',
|
|
95
95
|
} as const satisfies FunctionSelectors<typeof Abis.stablecoinDex>
|
|
96
96
|
|
|
97
|
+
export const storageCredits = {
|
|
98
|
+
balanceOf: '0x70a08231',
|
|
99
|
+
budgetOf: '0x7865e71f',
|
|
100
|
+
modeOf: '0x13668995',
|
|
101
|
+
setBudget: '0xffe295c3',
|
|
102
|
+
setMode: '0x21175b4a',
|
|
103
|
+
} as const satisfies FunctionSelectors<typeof Abis.storageCredits>
|
|
104
|
+
|
|
97
105
|
export const tip20 = {
|
|
98
106
|
BURN_BLOCKED_ROLE: '0x32ad9be8',
|
|
99
107
|
DOMAIN_SEPARATOR: '0x3644e515',
|
package/tempo/Transaction.ts
CHANGED
|
@@ -126,6 +126,16 @@ export type TransactionRequestTempo<
|
|
|
126
126
|
feeToken?: TempoAddress.Address | bigint | undefined
|
|
127
127
|
keyAuthorization?: KeyAuthorization.Signed<quantity, index> | undefined
|
|
128
128
|
multisig?: MultisigConfig.Config<index> | undefined
|
|
129
|
+
/** Bootstrap multisig config hint for node-side gas modeling (TIP-1061). Attached automatically when `multisig` is present; the node ignores it for registered senders. */
|
|
130
|
+
multisigInit?:
|
|
131
|
+
| {
|
|
132
|
+
salt: Hex.Hex
|
|
133
|
+
threshold: number
|
|
134
|
+
owners: readonly { owner: Address; weight: number }[]
|
|
135
|
+
}
|
|
136
|
+
| undefined
|
|
137
|
+
/** Modeled owner approval count for node-side gas modeling (TIP-1061). */
|
|
138
|
+
multisigSignatureCount?: number | undefined
|
|
129
139
|
nonceKey?: 'expiring' | quantity | undefined
|
|
130
140
|
signatures?: readonly SignatureEnvelope.Serialized[] | undefined
|
|
131
141
|
validBefore?: index | undefined
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Address } from 'abitype'
|
|
2
|
-
import type
|
|
2
|
+
import { type ReceivePolicyReceipt, VirtualAddress } from 'ox/tempo'
|
|
3
3
|
import type { Account } from '../../accounts/types.js'
|
|
4
4
|
import { parseAccount } from '../../accounts/utils/parseAccount.js'
|
|
5
5
|
import type { ReadContractReturnType } from '../../actions/public/readContract.js'
|
|
@@ -57,6 +57,25 @@ export type BlockedReason = ReceivePolicyReceipt.BlockedReason
|
|
|
57
57
|
/** @internal */
|
|
58
58
|
const blockedReasons = ['none', 'tokenFilter', 'receivePolicy'] as const
|
|
59
59
|
|
|
60
|
+
/** @internal 12-byte prefix shared by TIP-20 token addresses. */
|
|
61
|
+
const tip20Prefix = '0x20c000000000000000000000'
|
|
62
|
+
|
|
63
|
+
/** @internal */
|
|
64
|
+
const systemPrecompiles = [
|
|
65
|
+
Addresses.accountKeychain,
|
|
66
|
+
Addresses.accountRegistrar,
|
|
67
|
+
Addresses.addressRegistry,
|
|
68
|
+
Addresses.feeManager,
|
|
69
|
+
Addresses.nonceManager,
|
|
70
|
+
Addresses.receivePolicyGuard,
|
|
71
|
+
Addresses.signatureVerifier,
|
|
72
|
+
Addresses.stablecoinDex,
|
|
73
|
+
Addresses.tip20ChannelReserve,
|
|
74
|
+
Addresses.tip20Factory,
|
|
75
|
+
Addresses.tip403Registry,
|
|
76
|
+
Addresses.validator,
|
|
77
|
+
] as const
|
|
78
|
+
|
|
60
79
|
/**
|
|
61
80
|
* Claimer authorized to reclaim blocked funds.
|
|
62
81
|
*
|
|
@@ -1253,9 +1272,25 @@ function toPolicyRef(id: bigint): PolicyRef {
|
|
|
1253
1272
|
|
|
1254
1273
|
/** @internal */
|
|
1255
1274
|
function resolveClaimer(claimer: Claimer, self: Address): Address {
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1275
|
+
const recoveryAuthority =
|
|
1276
|
+
claimer === 'sender' ? zeroAddress : claimer === 'self' ? self : claimer
|
|
1277
|
+
assertValidRecoveryAuthority(recoveryAuthority)
|
|
1278
|
+
return recoveryAuthority
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
/** @internal */
|
|
1282
|
+
function assertValidRecoveryAuthority(recoveryAuthority: Address) {
|
|
1283
|
+
if (isAddressEqual(recoveryAuthority, zeroAddress)) return
|
|
1284
|
+
if (VirtualAddress.isVirtual(recoveryAuthority))
|
|
1285
|
+
throw new Error('Recovery authority cannot be a TIP-1022 virtual address.')
|
|
1286
|
+
if (recoveryAuthority.toLowerCase().startsWith(tip20Prefix))
|
|
1287
|
+
throw new Error('Recovery authority cannot be a TIP-20 token address.')
|
|
1288
|
+
if (
|
|
1289
|
+
systemPrecompiles.some((address) =>
|
|
1290
|
+
isAddressEqual(address, recoveryAuthority),
|
|
1291
|
+
)
|
|
1292
|
+
)
|
|
1293
|
+
throw new Error('Recovery authority cannot be a Tempo system precompile.')
|
|
1259
1294
|
}
|
|
1260
1295
|
|
|
1261
1296
|
/** @internal */
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Address } from 'abitype'
|
|
2
2
|
import * as Hex from 'ox/Hex'
|
|
3
|
+
import { VirtualAddress } from 'ox/tempo'
|
|
3
4
|
import type { Account } from '../../accounts/types.js'
|
|
4
5
|
import { readContract } from '../../actions/public/readContract.js'
|
|
5
6
|
import type { WriteContractReturnType } from '../../actions/wallet/writeContract.js'
|
|
@@ -121,7 +122,7 @@ export async function resolve<
|
|
|
121
122
|
client: Client<Transport, chain, account>,
|
|
122
123
|
parameters: resolve.Parameters,
|
|
123
124
|
): Promise<resolve.ReturnValue> {
|
|
124
|
-
if (!isVirtual(parameters.address)) return parameters.address
|
|
125
|
+
if (!VirtualAddress.isVirtual(parameters.address)) return parameters.address
|
|
125
126
|
|
|
126
127
|
const masterId = Hex.slice(parameters.address, 0, 4)
|
|
127
128
|
return getMasterAddress(client, { ...parameters, masterId })
|
|
@@ -328,10 +329,3 @@ export namespace registerMasterSync {
|
|
|
328
329
|
// TODO: exhaustive error type
|
|
329
330
|
export type ErrorType = BaseErrorType
|
|
330
331
|
}
|
|
331
|
-
|
|
332
|
-
const virtualMagic = '0xfdfdfdfdfdfdfdfdfdfd'
|
|
333
|
-
|
|
334
|
-
/** @internal */
|
|
335
|
-
function isVirtual(address: string): boolean {
|
|
336
|
-
return Hex.slice(address as Hex.Hex, 4, 14).toLowerCase() === virtualMagic
|
|
337
|
-
}
|
package/tempo/actions/zone.ts
CHANGED
|
@@ -26,7 +26,7 @@ import type {
|
|
|
26
26
|
ReadParameters,
|
|
27
27
|
WriteParameters,
|
|
28
28
|
} from '../internal/types.js'
|
|
29
|
-
import { defineCall } from '../internal/utils.js'
|
|
29
|
+
import { defineCall, pickWriteParameters } from '../internal/utils.js'
|
|
30
30
|
import * as Storage from '../Storage.js'
|
|
31
31
|
import type { TransactionReceipt } from '../Transaction.js'
|
|
32
32
|
import * as ZoneAbis from '../zones/Abis.js'
|
|
@@ -40,6 +40,23 @@ export type EncryptedPayload = {
|
|
|
40
40
|
tag: Hex.Hex
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
export type PreparedEncryptedDeposit = {
|
|
44
|
+
/** Amount of tokens to deposit. */
|
|
45
|
+
amount: bigint
|
|
46
|
+
/** Parent chain ID (e.g. `42431` for moderato). */
|
|
47
|
+
chainId: number
|
|
48
|
+
/** Encrypted deposit payload. */
|
|
49
|
+
encrypted: EncryptedPayload
|
|
50
|
+
/** Encryption key index from the portal contract. */
|
|
51
|
+
keyIndex: bigint
|
|
52
|
+
/** Zone portal address on the parent chain. */
|
|
53
|
+
portalAddress: Address
|
|
54
|
+
/** Token address or ID to deposit. */
|
|
55
|
+
token: TokenId.TokenIdOrAddress
|
|
56
|
+
/** Zone ID (e.g. `7`). */
|
|
57
|
+
zoneId: number
|
|
58
|
+
}
|
|
59
|
+
|
|
43
60
|
/**
|
|
44
61
|
* Deposits tokens into a zone on the parent Tempo chain.
|
|
45
62
|
* Batches approve and deposit into a single transaction.
|
|
@@ -269,46 +286,31 @@ export async function encryptedDeposit<
|
|
|
269
286
|
const account_ = account ? parseAccount(account) : undefined
|
|
270
287
|
if (!account) throw new Error('`account` is required.')
|
|
271
288
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
}),
|
|
283
|
-
readContract(client, {
|
|
284
|
-
address: portalAddress,
|
|
285
|
-
abi: ZoneAbis.zonePortal,
|
|
286
|
-
functionName: 'encryptionKeyCount',
|
|
287
|
-
}),
|
|
288
|
-
])
|
|
289
|
-
|
|
290
|
-
if (keyIndex === 0n) {
|
|
291
|
-
throw new Error('No sequencer encryption key configured.')
|
|
289
|
+
if ('encrypted' in parameters) {
|
|
290
|
+
if (parameters.chainId !== chainId) {
|
|
291
|
+
throw new Error(
|
|
292
|
+
'Prepared encrypted deposit chain ID does not match client chain.',
|
|
293
|
+
)
|
|
294
|
+
}
|
|
295
|
+
return sendTransaction(client, {
|
|
296
|
+
...pickWriteParameters(parameters as never),
|
|
297
|
+
calls: encryptedDeposit.calls(parameters),
|
|
298
|
+
} as never) as never
|
|
292
299
|
}
|
|
293
300
|
|
|
294
|
-
const
|
|
295
|
-
|
|
296
|
-
recipient,
|
|
297
|
-
portalAddress,
|
|
298
|
-
keyIndex - 1n,
|
|
299
|
-
parameters.memo,
|
|
300
|
-
)
|
|
301
|
+
const recipient = parameters.recipient ?? account_?.address
|
|
302
|
+
if (!recipient) throw new Error('`recipient` is required.')
|
|
301
303
|
|
|
302
|
-
const
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
encrypted,
|
|
306
|
-
keyIndex: keyIndex - 1n,
|
|
304
|
+
const prepared = await encryptedDeposit.prepare(client, {
|
|
305
|
+
amount: parameters.amount,
|
|
306
|
+
memo: parameters.memo,
|
|
307
307
|
recipient,
|
|
308
|
-
|
|
308
|
+
token: parameters.token,
|
|
309
|
+
zoneId: parameters.zoneId,
|
|
310
|
+
})
|
|
309
311
|
return sendTransaction(client, {
|
|
310
312
|
...rest,
|
|
311
|
-
calls: encryptedDeposit.calls(
|
|
313
|
+
calls: encryptedDeposit.calls(prepared),
|
|
312
314
|
} as never) as never
|
|
313
315
|
}
|
|
314
316
|
|
|
@@ -317,10 +319,13 @@ export namespace encryptedDeposit {
|
|
|
317
319
|
chain extends Chain | undefined = Chain | undefined,
|
|
318
320
|
account extends Account | undefined = Account | undefined,
|
|
319
321
|
> = WriteParameters<chain, account> &
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
322
|
+
(
|
|
323
|
+
| (Omit<Args, 'chainId' | 'encrypted' | 'keyIndex' | 'recipient'> & {
|
|
324
|
+
/** Recipient address in the zone. @default `account.address` */
|
|
325
|
+
recipient?: Address | undefined
|
|
326
|
+
})
|
|
327
|
+
| PreparedEncryptedDeposit
|
|
328
|
+
)
|
|
324
329
|
|
|
325
330
|
export type Args = {
|
|
326
331
|
/** Amount of tokens to deposit. */
|
|
@@ -346,13 +351,111 @@ export namespace encryptedDeposit {
|
|
|
346
351
|
// TODO: exhaustive error type
|
|
347
352
|
export type ErrorType = BaseErrorType
|
|
348
353
|
|
|
354
|
+
/**
|
|
355
|
+
* Prepares an encrypted deposit instruction without broadcasting it.
|
|
356
|
+
*
|
|
357
|
+
* @example
|
|
358
|
+
* ```ts
|
|
359
|
+
* import { createClient, http } from 'viem'
|
|
360
|
+
* import { tempoModerato } from 'viem/chains'
|
|
361
|
+
* import { Actions } from 'viem/tempo'
|
|
362
|
+
*
|
|
363
|
+
* const client = createClient({
|
|
364
|
+
* chain: tempoModerato,
|
|
365
|
+
* transport: http(),
|
|
366
|
+
* })
|
|
367
|
+
*
|
|
368
|
+
* const prepared = await Actions.zone.encryptedDeposit.prepare(client, {
|
|
369
|
+
* token: '0x20c0...0001',
|
|
370
|
+
* amount: 1_000_000n,
|
|
371
|
+
* recipient: '0x...',
|
|
372
|
+
* zoneId: 7,
|
|
373
|
+
* })
|
|
374
|
+
* ```
|
|
375
|
+
*
|
|
376
|
+
* @param client - Public client connected to the parent Tempo chain.
|
|
377
|
+
* @param parameters - Encrypted deposit preparation parameters.
|
|
378
|
+
* @returns A prepared encrypted deposit instruction.
|
|
379
|
+
*/
|
|
380
|
+
export async function prepare<
|
|
381
|
+
chain extends Chain | undefined,
|
|
382
|
+
account extends Account | undefined,
|
|
383
|
+
>(
|
|
384
|
+
client: Client<Transport, chain, account>,
|
|
385
|
+
parameters: prepare.Parameters,
|
|
386
|
+
): Promise<prepare.ReturnValue> {
|
|
387
|
+
const chainId = client.chain?.id
|
|
388
|
+
if (!chainId) throw new Error('`chain` is required.')
|
|
389
|
+
|
|
390
|
+
const { amount, memo, recipient, token, zoneId, ...rest } = parameters
|
|
391
|
+
const portalAddress = getPortalAddress(chainId, zoneId)
|
|
392
|
+
|
|
393
|
+
const [publicKey, keyIndex] = await Promise.all([
|
|
394
|
+
readContract(client, {
|
|
395
|
+
...rest,
|
|
396
|
+
address: portalAddress,
|
|
397
|
+
abi: ZoneAbis.zonePortal,
|
|
398
|
+
functionName: 'sequencerEncryptionKey',
|
|
399
|
+
}),
|
|
400
|
+
readContract(client, {
|
|
401
|
+
...rest,
|
|
402
|
+
address: portalAddress,
|
|
403
|
+
abi: ZoneAbis.zonePortal,
|
|
404
|
+
functionName: 'encryptionKeyCount',
|
|
405
|
+
}),
|
|
406
|
+
])
|
|
407
|
+
|
|
408
|
+
if (keyIndex === 0n) {
|
|
409
|
+
throw new Error('No sequencer encryption key configured.')
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
const encrypted = await encryptDepositPayload(
|
|
413
|
+
{ x: publicKey[0], yParity: publicKey[1] },
|
|
414
|
+
recipient,
|
|
415
|
+
portalAddress,
|
|
416
|
+
keyIndex - 1n,
|
|
417
|
+
memo,
|
|
418
|
+
)
|
|
419
|
+
|
|
420
|
+
return {
|
|
421
|
+
amount,
|
|
422
|
+
chainId,
|
|
423
|
+
encrypted,
|
|
424
|
+
keyIndex: keyIndex - 1n,
|
|
425
|
+
portalAddress,
|
|
426
|
+
token,
|
|
427
|
+
zoneId,
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
export namespace prepare {
|
|
432
|
+
export type Parameters = ReadParameters & Args
|
|
433
|
+
|
|
434
|
+
export type Args = {
|
|
435
|
+
/** Amount of tokens to deposit. */
|
|
436
|
+
amount: bigint
|
|
437
|
+
/** Optional deposit memo. @default `0x00...00` */
|
|
438
|
+
memo?: Hex.Hex | undefined
|
|
439
|
+
/** Recipient address in the zone. */
|
|
440
|
+
recipient: Address
|
|
441
|
+
/** Token address or ID to deposit. */
|
|
442
|
+
token: TokenId.TokenIdOrAddress
|
|
443
|
+
/** Zone ID (e.g. `7`). */
|
|
444
|
+
zoneId: number
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
export type ReturnValue = PreparedEncryptedDeposit
|
|
448
|
+
|
|
449
|
+
export type ErrorType = RequestErrorType | BaseErrorType
|
|
450
|
+
}
|
|
451
|
+
|
|
349
452
|
/**
|
|
350
453
|
* Defines the calls to approve and deposit tokens into a zone (encrypted).
|
|
351
454
|
*
|
|
352
455
|
* @param args - Arguments.
|
|
353
456
|
* @returns The calls.
|
|
354
457
|
*/
|
|
355
|
-
export function calls(args: Args) {
|
|
458
|
+
export function calls(args: Args | PreparedEncryptedDeposit) {
|
|
356
459
|
const { amount, chainId, encrypted, keyIndex, token, zoneId } = args
|
|
357
460
|
const portalAddress = getPortalAddress(chainId, zoneId)
|
|
358
461
|
return [
|
|
@@ -430,47 +533,34 @@ export async function encryptedDepositSync<
|
|
|
430
533
|
const account_ = account ? parseAccount(account) : undefined
|
|
431
534
|
if (!account) throw new Error('`account` is required.')
|
|
432
535
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
})
|
|
444
|
-
|
|
445
|
-
address: portalAddress,
|
|
446
|
-
abi: ZoneAbis.zonePortal,
|
|
447
|
-
functionName: 'encryptionKeyCount',
|
|
448
|
-
}),
|
|
449
|
-
])
|
|
450
|
-
|
|
451
|
-
if (keyIndex === 0n) {
|
|
452
|
-
throw new Error('No sequencer encryption key configured.')
|
|
536
|
+
if ('encrypted' in parameters) {
|
|
537
|
+
if (parameters.chainId !== chainId) {
|
|
538
|
+
throw new Error(
|
|
539
|
+
'Prepared encrypted deposit chain ID does not match client chain.',
|
|
540
|
+
)
|
|
541
|
+
}
|
|
542
|
+
const receipt = await sendTransactionSync(client, {
|
|
543
|
+
...pickWriteParameters(parameters as never),
|
|
544
|
+
throwOnReceiptRevert,
|
|
545
|
+
calls: encryptedDeposit.calls(parameters),
|
|
546
|
+
} as never)
|
|
547
|
+
return { receipt }
|
|
453
548
|
}
|
|
454
549
|
|
|
455
|
-
const
|
|
456
|
-
|
|
457
|
-
recipient,
|
|
458
|
-
portalAddress,
|
|
459
|
-
keyIndex - 1n,
|
|
460
|
-
parameters.memo,
|
|
461
|
-
)
|
|
550
|
+
const recipient = parameters.recipient ?? account_?.address
|
|
551
|
+
if (!recipient) throw new Error('`recipient` is required.')
|
|
462
552
|
|
|
463
|
-
const
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
encrypted,
|
|
467
|
-
keyIndex: keyIndex - 1n,
|
|
553
|
+
const prepared = await encryptedDeposit.prepare(client, {
|
|
554
|
+
amount: parameters.amount,
|
|
555
|
+
memo: parameters.memo,
|
|
468
556
|
recipient,
|
|
469
|
-
|
|
557
|
+
token: parameters.token,
|
|
558
|
+
zoneId: parameters.zoneId,
|
|
559
|
+
})
|
|
470
560
|
const receipt = await sendTransactionSync(client, {
|
|
471
561
|
...rest,
|
|
472
562
|
throwOnReceiptRevert,
|
|
473
|
-
calls: encryptedDeposit.calls(
|
|
563
|
+
calls: encryptedDeposit.calls(prepared),
|
|
474
564
|
} as never)
|
|
475
565
|
return { receipt }
|
|
476
566
|
}
|
package/tempo/chainConfig.ts
CHANGED
|
@@ -83,8 +83,17 @@ export const chainConfig = {
|
|
|
83
83
|
? (request.account as MultisigAccount).config
|
|
84
84
|
: undefined)
|
|
85
85
|
if (multisig) {
|
|
86
|
-
|
|
87
|
-
request.
|
|
86
|
+
const config = MultisigConfig.from(multisig)
|
|
87
|
+
request.multisig = config
|
|
88
|
+
request.from = MultisigConfig.getAddress(config)
|
|
89
|
+
request.multisigInit = {
|
|
90
|
+
salt: config.salt ?? MultisigConfig.zeroSalt,
|
|
91
|
+
threshold: Number(config.threshold),
|
|
92
|
+
owners: config.owners.map((owner) => ({
|
|
93
|
+
owner: owner.owner,
|
|
94
|
+
weight: Number(owner.weight),
|
|
95
|
+
})),
|
|
96
|
+
}
|
|
88
97
|
// A non-multisig `account` (e.g. the client's default) isn't the sender,
|
|
89
98
|
// so drop it: core then fills nonce/gas/fees for the multisig sender via
|
|
90
99
|
// `request.from`. A multisig account *is* the sender — keep it so the
|
|
@@ -75,7 +75,9 @@ export function decodeAbiParameters<
|
|
|
75
75
|
const values = []
|
|
76
76
|
for (let i = 0; i < params.length; ++i) {
|
|
77
77
|
const param = params[i]
|
|
78
|
-
|
|
78
|
+
// Zero-width types (e.g. `uint256[0]`, empty tuples) at the end of the
|
|
79
|
+
// data consume no bytes, so the cursor may already be exhausted.
|
|
80
|
+
if (consumed < bytes.length) cursor.setPosition(consumed)
|
|
79
81
|
const [data, consumed_] = decodeParameter(cursor, param, {
|
|
80
82
|
staticPosition: 0,
|
|
81
83
|
})
|
|
@@ -146,7 +148,8 @@ function decodeArray(
|
|
|
146
148
|
) {
|
|
147
149
|
// If the length of the array is not known in advance (dynamic array),
|
|
148
150
|
// this means we will need to wonder off to the pointer and decode.
|
|
149
|
-
|
|
151
|
+
// Note: zero-length fixed arrays (`T[0]`) are not dynamic.
|
|
152
|
+
if (length === null) {
|
|
150
153
|
// Dealing with a dynamic type, so get the offset of the array data.
|
|
151
154
|
const offset = bytesToNumber(cursor.readBytes(sizeOfOffset))
|
|
152
155
|
|
|
@@ -172,6 +175,12 @@ function decodeArray(
|
|
|
172
175
|
})
|
|
173
176
|
consumed += consumed_
|
|
174
177
|
value.push(data)
|
|
178
|
+
// Charge zero-width elements against the read limit to bound work
|
|
179
|
+
// on huge lengths of zero-width types (e.g. `uint256[0][]`).
|
|
180
|
+
if (consumed_ === 0) {
|
|
181
|
+
cursor.assertReadLimit()
|
|
182
|
+
cursor._touch()
|
|
183
|
+
}
|
|
175
184
|
}
|
|
176
185
|
|
|
177
186
|
// As we have gone wondering, restore to the original position + next slot.
|
|
@@ -214,6 +223,12 @@ function decodeArray(
|
|
|
214
223
|
})
|
|
215
224
|
consumed += consumed_
|
|
216
225
|
value.push(data)
|
|
226
|
+
// Charge zero-width elements against the read limit to bound work
|
|
227
|
+
// on huge lengths of zero-width types (e.g. `uint256[0][4294967295]`).
|
|
228
|
+
if (consumed_ === 0) {
|
|
229
|
+
cursor.assertReadLimit()
|
|
230
|
+
cursor._touch()
|
|
231
|
+
}
|
|
217
232
|
}
|
|
218
233
|
return [value, consumed]
|
|
219
234
|
}
|