viem 2.55.17 → 2.55.19
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 +16 -0
- package/_cjs/chains/definitions/morphTachyon.js +25 -0
- package/_cjs/chains/definitions/morphTachyon.js.map +1 -0
- package/_cjs/chains/definitions/morphTachyonTestnet.js +26 -0
- package/_cjs/chains/definitions/morphTachyonTestnet.js.map +1 -0
- package/_cjs/chains/definitions/ynxTestnet.js +26 -0
- package/_cjs/chains/definitions/ynxTestnet.js.map +1 -0
- package/_cjs/chains/index.js +13 -7
- package/_cjs/chains/index.js.map +1 -1
- package/_cjs/errors/version.js +1 -1
- package/_cjs/tempo/Abis.js +102 -1
- package/_cjs/tempo/Abis.js.map +1 -1
- package/_cjs/tempo/Account.js +188 -16
- package/_cjs/tempo/Account.js.map +1 -1
- package/_cjs/tempo/Addresses.js +2 -1
- package/_cjs/tempo/Addresses.js.map +1 -1
- package/_cjs/tempo/Decorator.js +8 -0
- package/_cjs/tempo/Decorator.js.map +1 -1
- package/_cjs/tempo/Formatters.js +1 -1
- package/_cjs/tempo/Formatters.js.map +1 -1
- package/_cjs/tempo/Selectors.js +7 -1
- package/_cjs/tempo/Selectors.js.map +1 -1
- package/_cjs/tempo/Transaction.js +31 -10
- package/_cjs/tempo/Transaction.js.map +1 -1
- package/_cjs/tempo/actions/accessKey.js +49 -8
- package/_cjs/tempo/actions/accessKey.js.map +1 -1
- package/_cjs/tempo/actions/earn.js +12 -4
- package/_cjs/tempo/actions/earn.js.map +1 -1
- package/_cjs/tempo/actions/index.js +2 -1
- package/_cjs/tempo/actions/index.js.map +1 -1
- package/_cjs/tempo/actions/multisig.js +95 -0
- package/_cjs/tempo/actions/multisig.js.map +1 -0
- package/_cjs/tempo/actions/zone.js +16 -16
- package/_cjs/tempo/actions/zone.js.map +1 -1
- package/_cjs/tempo/chainConfig.js +58 -29
- package/_cjs/tempo/chainConfig.js.map +1 -1
- package/_cjs/tempo/internal/multisig.js +56 -0
- package/_cjs/tempo/internal/multisig.js.map +1 -0
- package/_cjs/tempo/zones/Abis.js +2 -2
- package/_cjs/tempo/zones/Abis.js.map +1 -1
- package/_esm/chains/definitions/morphTachyon.js +22 -0
- package/_esm/chains/definitions/morphTachyon.js.map +1 -0
- package/_esm/chains/definitions/morphTachyonTestnet.js +23 -0
- package/_esm/chains/definitions/morphTachyonTestnet.js.map +1 -0
- package/_esm/chains/definitions/ynxTestnet.js +23 -0
- package/_esm/chains/definitions/ynxTestnet.js.map +1 -0
- package/_esm/chains/index.js +3 -0
- package/_esm/chains/index.js.map +1 -1
- package/_esm/errors/version.js +1 -1
- package/_esm/tempo/Abis.js +101 -0
- package/_esm/tempo/Abis.js.map +1 -1
- package/_esm/tempo/Account.js +196 -66
- package/_esm/tempo/Account.js.map +1 -1
- package/_esm/tempo/Addresses.js +1 -0
- package/_esm/tempo/Addresses.js.map +1 -1
- package/_esm/tempo/Decorator.js +8 -0
- package/_esm/tempo/Decorator.js.map +1 -1
- package/_esm/tempo/Formatters.js +3 -6
- package/_esm/tempo/Formatters.js.map +1 -1
- package/_esm/tempo/Selectors.js +6 -0
- package/_esm/tempo/Selectors.js.map +1 -1
- package/_esm/tempo/Transaction.js +31 -10
- package/_esm/tempo/Transaction.js.map +1 -1
- package/_esm/tempo/actions/accessKey.js +65 -23
- package/_esm/tempo/actions/accessKey.js.map +1 -1
- package/_esm/tempo/actions/earn.js +14 -6
- package/_esm/tempo/actions/earn.js.map +1 -1
- package/_esm/tempo/actions/index.js +1 -0
- package/_esm/tempo/actions/index.js.map +1 -1
- package/_esm/tempo/actions/multisig.js +245 -0
- package/_esm/tempo/actions/multisig.js.map +1 -0
- package/_esm/tempo/actions/zone.js +17 -17
- package/_esm/tempo/actions/zone.js.map +1 -1
- package/_esm/tempo/chainConfig.js +65 -35
- package/_esm/tempo/chainConfig.js.map +1 -1
- package/_esm/tempo/internal/multisig.js +56 -0
- package/_esm/tempo/internal/multisig.js.map +1 -0
- package/_esm/tempo/zones/Abis.js +2 -2
- package/_esm/tempo/zones/Abis.js.map +1 -1
- package/_types/chains/definitions/morphTachyon.d.ts +51 -0
- package/_types/chains/definitions/morphTachyon.d.ts.map +1 -0
- package/_types/chains/definitions/morphTachyonTestnet.d.ts +51 -0
- package/_types/chains/definitions/morphTachyonTestnet.d.ts.map +1 -0
- package/_types/chains/definitions/tempo.d.ts +30 -2
- package/_types/chains/definitions/tempo.d.ts.map +1 -1
- package/_types/chains/definitions/tempoDevnet.d.ts +30 -2
- package/_types/chains/definitions/tempoDevnet.d.ts.map +1 -1
- package/_types/chains/definitions/tempoLocalnet.d.ts +30 -2
- package/_types/chains/definitions/tempoLocalnet.d.ts.map +1 -1
- package/_types/chains/definitions/tempoModerato.d.ts +30 -2
- package/_types/chains/definitions/tempoModerato.d.ts.map +1 -1
- package/_types/chains/definitions/ynxTestnet.d.ts +51 -0
- package/_types/chains/definitions/ynxTestnet.d.ts.map +1 -0
- package/_types/chains/index.d.ts +3 -0
- package/_types/chains/index.d.ts.map +1 -1
- package/_types/errors/version.d.ts +1 -1
- package/_types/tempo/Abis.d.ts +321 -0
- package/_types/tempo/Abis.d.ts.map +1 -1
- package/_types/tempo/Account.d.ts +42 -26
- package/_types/tempo/Account.d.ts.map +1 -1
- package/_types/tempo/Addresses.d.ts +1 -0
- package/_types/tempo/Addresses.d.ts.map +1 -1
- package/_types/tempo/Decorator.d.ts +34 -2
- package/_types/tempo/Decorator.d.ts.map +1 -1
- package/_types/tempo/Formatters.d.ts.map +1 -1
- package/_types/tempo/Selectors.d.ts +6 -0
- package/_types/tempo/Selectors.d.ts.map +1 -1
- package/_types/tempo/Transaction.d.ts +17 -2
- package/_types/tempo/Transaction.d.ts.map +1 -1
- package/_types/tempo/actions/accessKey.d.ts +35 -17
- package/_types/tempo/actions/accessKey.d.ts.map +1 -1
- package/_types/tempo/actions/earn.d.ts +5 -5
- package/_types/tempo/actions/earn.d.ts.map +1 -1
- package/_types/tempo/actions/index.d.ts +1 -0
- package/_types/tempo/actions/index.d.ts.map +1 -1
- package/_types/tempo/actions/multisig.d.ts +472 -0
- package/_types/tempo/actions/multisig.d.ts.map +1 -0
- package/_types/tempo/actions/zone.d.ts +17 -17
- package/_types/tempo/actions/zone.d.ts.map +1 -1
- package/_types/tempo/chainConfig.d.ts +15 -1
- package/_types/tempo/chainConfig.d.ts.map +1 -1
- package/_types/tempo/internal/multisig.d.ts +13 -0
- package/_types/tempo/internal/multisig.d.ts.map +1 -0
- package/_types/tempo/zones/Abis.d.ts +2 -2
- package/_types/tempo/zones/zone.d.ts +90 -6
- package/_types/tempo/zones/zone.d.ts.map +1 -1
- package/chains/definitions/morphTachyon.ts +22 -0
- package/chains/definitions/morphTachyonTestnet.ts +23 -0
- package/chains/definitions/ynxTestnet.ts +23 -0
- package/chains/index.ts +3 -0
- package/errors/version.ts +1 -1
- package/package.json +2 -2
- package/tempo/Abis.ts +102 -0
- package/tempo/Account.ts +329 -51
- package/tempo/Addresses.ts +1 -0
- package/tempo/Decorator.ts +52 -2
- package/tempo/Formatters.ts +4 -5
- package/tempo/Selectors.ts +7 -0
- package/tempo/Transaction.ts +52 -12
- package/tempo/actions/accessKey.ts +128 -32
- package/tempo/actions/earn.ts +19 -11
- package/tempo/actions/index.ts +1 -0
- package/tempo/actions/multisig.ts +356 -0
- package/tempo/actions/zone.ts +35 -31
- package/tempo/chainConfig.ts +82 -35
- package/tempo/internal/multisig.ts +72 -0
- package/tempo/zones/Abis.ts +2 -2
package/tempo/chainConfig.ts
CHANGED
|
@@ -15,9 +15,14 @@ import { keccak256 } from '../utils/hash/keccak256.js'
|
|
|
15
15
|
import type { SerializeTransactionFn } from '../utils/transaction/serializeTransaction.js'
|
|
16
16
|
import type { Account, MultisigAccount } from './Account.js'
|
|
17
17
|
import { getMetadata } from './actions/accessKey.js'
|
|
18
|
+
import * as multisig from './actions/multisig.js'
|
|
18
19
|
import * as Formatters from './Formatters.js'
|
|
19
20
|
import type { Hardfork } from './Hardfork.js'
|
|
20
21
|
import * as Concurrent from './internal/concurrent.js'
|
|
22
|
+
import {
|
|
23
|
+
createMultisigStateResolver,
|
|
24
|
+
getMultisigOwnerStates,
|
|
25
|
+
} from './internal/multisig.js'
|
|
21
26
|
import * as Transaction from './Transaction.js'
|
|
22
27
|
|
|
23
28
|
const maxExpirySecs = 25
|
|
@@ -60,7 +65,10 @@ export const chainConfig = {
|
|
|
60
65
|
| undefined
|
|
61
66
|
feePayerSignature?: Transaction.TransactionSerializableTempo['feePayerSignature']
|
|
62
67
|
from?: Address | undefined
|
|
63
|
-
|
|
68
|
+
keyData?: Hex.Hex | undefined
|
|
69
|
+
keyType?: 'p256' | 'secp256k1' | 'webAuthn' | undefined
|
|
70
|
+
multisig?: Address | MultisigConfig.Config | undefined
|
|
71
|
+
multisigOwnerStates?: Transaction.TransactionRequestTempo['multisigOwnerStates']
|
|
64
72
|
signatures?: readonly unknown[] | undefined
|
|
65
73
|
}
|
|
66
74
|
|
|
@@ -82,36 +90,88 @@ export const chainConfig = {
|
|
|
82
90
|
return request as unknown as typeof r
|
|
83
91
|
}
|
|
84
92
|
|
|
85
|
-
// Native multisig (TIP-1061). The transaction sender is the
|
|
86
|
-
// multisig
|
|
87
|
-
//
|
|
88
|
-
//
|
|
89
|
-
// serializer auto-detects bootstrap (`init`) from `nonce == 0`.
|
|
93
|
+
// Native multisig (TIP-1061). The transaction sender is the stable
|
|
94
|
+
// multisig address, not a signing account. Initial configs support
|
|
95
|
+
// bootstrap; initialized accounts can be reconstructed from their
|
|
96
|
+
// address and resolved through the multisig precompile.
|
|
90
97
|
//
|
|
91
98
|
// The config is taken from an explicit `multisig` field, or inferred from
|
|
92
99
|
// a multisig account (so callers can just pass `account` to
|
|
93
100
|
// `prepareTransactionRequest` without also passing `multisig`).
|
|
94
|
-
const
|
|
101
|
+
const multisigIdentity =
|
|
95
102
|
request.multisig ??
|
|
96
103
|
(request.account?.source === 'multisig'
|
|
97
|
-
? (request.account as MultisigAccount).config
|
|
104
|
+
? ((request.account as MultisigAccount).config ??
|
|
105
|
+
request.account.address)
|
|
98
106
|
: undefined)
|
|
99
|
-
if (
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
107
|
+
if (multisigIdentity) {
|
|
108
|
+
const initialConfig =
|
|
109
|
+
typeof multisigIdentity === 'string'
|
|
110
|
+
? undefined
|
|
111
|
+
: MultisigConfig.from(multisigIdentity)
|
|
112
|
+
const multisigAddress =
|
|
113
|
+
typeof multisigIdentity === 'string'
|
|
114
|
+
? multisigIdentity
|
|
115
|
+
: MultisigConfig.getAddress(initialConfig!)
|
|
116
|
+
request.multisig = initialConfig ?? multisigIdentity
|
|
117
|
+
request.from = multisigAddress
|
|
118
|
+
// Key types are not part of the config, so conservatively model every
|
|
119
|
+
// approval as a maximum-size WebAuthn signature.
|
|
120
|
+
if (typeof request.keyType === 'undefined') {
|
|
121
|
+
request.keyType = 'webAuthn'
|
|
122
|
+
if (typeof request.keyData === 'undefined') request.keyData = '0x0578'
|
|
123
|
+
}
|
|
124
|
+
const getState = createMultisigStateResolver((account) =>
|
|
125
|
+
getAction(client, multisig.getConfig, 'getConfig')({ account }),
|
|
126
|
+
)
|
|
127
|
+
const ownerStates =
|
|
128
|
+
request.account?.source === 'multisig'
|
|
129
|
+
? getMultisigOwnerStates(
|
|
130
|
+
request.account as MultisigAccount,
|
|
131
|
+
getState,
|
|
132
|
+
)
|
|
133
|
+
: undefined
|
|
134
|
+
const state = ownerStates
|
|
135
|
+
? (await ownerStates)[0]!
|
|
136
|
+
: await getState(multisigAddress)
|
|
137
|
+
if (!initialConfig && !state.initialized)
|
|
138
|
+
throw new Error(
|
|
139
|
+
'Cannot prepare an uninitialized multisig account from an address. Provide its initial config instead.',
|
|
140
|
+
)
|
|
141
|
+
if (typeof request.multisigVersion === 'undefined')
|
|
142
|
+
request.multisigVersion = state.version
|
|
143
|
+
const authorizationSignature = request.keyAuthorization?.signature
|
|
144
|
+
if (
|
|
145
|
+
authorizationSignature?.type === 'multisig' &&
|
|
146
|
+
typeof authorizationSignature.init !== 'undefined'
|
|
147
|
+
)
|
|
148
|
+
request.keyAuthorization = {
|
|
149
|
+
...request.keyAuthorization!,
|
|
150
|
+
signature: SignatureEnvelope.from({
|
|
151
|
+
initialConfig: authorizationSignature.init,
|
|
152
|
+
signatures: authorizationSignature.signatures,
|
|
153
|
+
}),
|
|
154
|
+
}
|
|
155
|
+
const keyAuthorizationSignature = request.keyAuthorization?.signature
|
|
156
|
+
const keyAuthorizationInitializes =
|
|
157
|
+
keyAuthorizationSignature?.type === 'multisig' &&
|
|
158
|
+
typeof keyAuthorizationSignature.init !== 'undefined'
|
|
159
|
+
if (initialConfig && !keyAuthorizationInitializes)
|
|
160
|
+
request.multisigInit = {
|
|
161
|
+
salt: initialConfig.salt ?? MultisigConfig.zeroSalt,
|
|
162
|
+
threshold: Number(initialConfig.threshold),
|
|
163
|
+
owners: initialConfig.owners.map((owner) => ({
|
|
164
|
+
owner: owner.owner,
|
|
165
|
+
weight: Number(owner.weight),
|
|
166
|
+
})),
|
|
167
|
+
}
|
|
168
|
+
if (ownerStates) {
|
|
169
|
+
const states = await ownerStates
|
|
170
|
+
if (states.length > 0) request.multisigOwnerStates = states
|
|
110
171
|
}
|
|
111
|
-
request.multisigSignatureCount ??= inferMultisigSignatureCount(config)
|
|
112
172
|
// A non-multisig `account` (e.g. the client's default) isn't the sender,
|
|
113
173
|
// so drop it: core then fills nonce/gas/fees for the multisig sender via
|
|
114
|
-
// `request.from`. A multisig account *is* the sender
|
|
174
|
+
// `request.from`. A multisig account *is* the sender, so keep it so the
|
|
115
175
|
// prepared request can be sent without re-passing `account`.
|
|
116
176
|
if (request.account?.source !== 'multisig') delete request.account
|
|
117
177
|
}
|
|
@@ -121,7 +181,7 @@ export const chainConfig = {
|
|
|
121
181
|
const useExpiringNonce = await (async () => {
|
|
122
182
|
if (request.nonceKey === 'expiring' || request.nonceKey === maxUint256)
|
|
123
183
|
return true
|
|
124
|
-
if (
|
|
184
|
+
if (multisigIdentity) return false
|
|
125
185
|
if (request.feePayer && typeof request.nonceKey === 'undefined')
|
|
126
186
|
return true
|
|
127
187
|
const account = request.account as
|
|
@@ -286,16 +346,3 @@ export const chainConfig = {
|
|
|
286
346
|
} as const satisfies viem_ChainConfig & { blockTime: number }
|
|
287
347
|
|
|
288
348
|
export type ChainConfig = typeof chainConfig
|
|
289
|
-
|
|
290
|
-
function inferMultisigSignatureCount(config: MultisigConfig.Config) {
|
|
291
|
-
const threshold = Number(config.threshold)
|
|
292
|
-
const weights = config.owners
|
|
293
|
-
.map((owner) => Number(owner.weight))
|
|
294
|
-
.sort((a, b) => b - a)
|
|
295
|
-
let total = 0
|
|
296
|
-
for (const [index, weight] of weights.entries()) {
|
|
297
|
-
total += weight
|
|
298
|
-
if (total >= threshold) return index + 1
|
|
299
|
-
}
|
|
300
|
-
return weights.length
|
|
301
|
-
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { Address } from 'abitype'
|
|
2
|
+
import type { MultisigConfig } from 'ox/tempo'
|
|
3
|
+
import { BaseError } from '../../errors/base.js'
|
|
4
|
+
import { ContractFunctionRevertedError } from '../../errors/contract.js'
|
|
5
|
+
import type { MultisigAccount } from '../Account.js'
|
|
6
|
+
import type { MultisigOwnerState } from '../Transaction.js'
|
|
7
|
+
|
|
8
|
+
/** @internal */
|
|
9
|
+
export function createMultisigStateResolver(
|
|
10
|
+
getConfig: (account: Address) => Promise<{
|
|
11
|
+
owners: MultisigConfig.Config['owners']
|
|
12
|
+
threshold: MultisigConfig.Config['threshold']
|
|
13
|
+
version: bigint
|
|
14
|
+
}>,
|
|
15
|
+
) {
|
|
16
|
+
// Cache only within one operation because config versions can change between requests.
|
|
17
|
+
const cache = new Map<Address, Promise<MultisigOwnerState>>()
|
|
18
|
+
return (account: Address): Promise<MultisigOwnerState> => {
|
|
19
|
+
const address = account.toLowerCase() as Address
|
|
20
|
+
const cached = cache.get(address)
|
|
21
|
+
if (cached) return cached
|
|
22
|
+
|
|
23
|
+
const state = (async () => {
|
|
24
|
+
try {
|
|
25
|
+
const config = await getConfig(account)
|
|
26
|
+
return {
|
|
27
|
+
account,
|
|
28
|
+
config: { owners: config.owners, threshold: config.threshold },
|
|
29
|
+
initialized: true,
|
|
30
|
+
version: config.version,
|
|
31
|
+
}
|
|
32
|
+
} catch (error) {
|
|
33
|
+
const cause =
|
|
34
|
+
error instanceof BaseError
|
|
35
|
+
? error.walk(
|
|
36
|
+
(error) => error instanceof ContractFunctionRevertedError,
|
|
37
|
+
)
|
|
38
|
+
: undefined
|
|
39
|
+
if (
|
|
40
|
+
!(cause instanceof ContractFunctionRevertedError) ||
|
|
41
|
+
cause.data?.errorName !== 'NotMultisigAccount'
|
|
42
|
+
)
|
|
43
|
+
throw error
|
|
44
|
+
return { account, initialized: false, version: 0n }
|
|
45
|
+
}
|
|
46
|
+
})()
|
|
47
|
+
cache.set(address, state)
|
|
48
|
+
return state
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** @internal */
|
|
53
|
+
export function getMultisigOwnerStates(
|
|
54
|
+
account: MultisigAccount,
|
|
55
|
+
getState: (account: Address) => Promise<MultisigOwnerState>,
|
|
56
|
+
): Promise<readonly MultisigOwnerState[]> {
|
|
57
|
+
// Collect locally first so all config reads start in one latency wave.
|
|
58
|
+
const owners: MultisigAccount[] = [account]
|
|
59
|
+
const seen = new Set<Address>([account.address.toLowerCase() as Address])
|
|
60
|
+
const visit = (account: MultisigAccount) => {
|
|
61
|
+
for (const owner of account.owners) {
|
|
62
|
+
if (owner.source !== 'multisig') continue
|
|
63
|
+
const address = owner.address.toLowerCase() as Address
|
|
64
|
+
if (seen.has(address)) continue
|
|
65
|
+
seen.add(address)
|
|
66
|
+
owners.push(owner as MultisigAccount)
|
|
67
|
+
visit(owner as MultisigAccount)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
visit(account)
|
|
71
|
+
return Promise.all(owners.map((owner) => getState(owner.address)))
|
|
72
|
+
}
|
package/tempo/zones/Abis.ts
CHANGED
|
@@ -121,7 +121,7 @@ export const zonePortal = [
|
|
|
121
121
|
{ name: 'to', type: 'address' },
|
|
122
122
|
{ name: 'amount', type: 'uint128' },
|
|
123
123
|
{ name: 'memo', type: 'bytes32' },
|
|
124
|
-
{ name: '
|
|
124
|
+
{ name: 'tempoRefundRecipient', type: 'address' },
|
|
125
125
|
],
|
|
126
126
|
outputs: [{ name: '', type: 'bytes32' }],
|
|
127
127
|
},
|
|
@@ -144,7 +144,7 @@ export const zonePortal = [
|
|
|
144
144
|
{ name: 'tag', type: 'bytes16' },
|
|
145
145
|
],
|
|
146
146
|
},
|
|
147
|
-
{ name: '
|
|
147
|
+
{ name: 'tempoRefundRecipient', type: 'address' },
|
|
148
148
|
],
|
|
149
149
|
outputs: [{ name: '', type: 'bytes32' }],
|
|
150
150
|
},
|