ox 1.0.0-beta.13 → 1.0.0-beta.15
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/dist/tempo/Channel.d.ts +8 -14
- package/dist/tempo/Channel.d.ts.map +1 -1
- package/dist/tempo/Channel.js +4 -8
- package/dist/tempo/Channel.js.map +1 -1
- package/dist/tempo/PoolId.d.ts +7 -7
- package/dist/tempo/PoolId.d.ts.map +1 -1
- package/dist/tempo/PoolId.js +9 -6
- package/dist/tempo/PoolId.js.map +1 -1
- package/dist/tempo/TransactionRequest.d.ts +15 -2
- package/dist/tempo/TransactionRequest.d.ts.map +1 -1
- package/dist/tempo/TransactionRequest.js +65 -29
- package/dist/tempo/TransactionRequest.js.map +1 -1
- package/dist/tempo/TxEnvelopeTempo.d.ts +2 -3
- package/dist/tempo/TxEnvelopeTempo.d.ts.map +1 -1
- package/dist/tempo/TxEnvelopeTempo.js +5 -6
- package/dist/tempo/TxEnvelopeTempo.js.map +1 -1
- package/dist/tempo/index.d.ts +3 -24
- package/dist/tempo/index.d.ts.map +1 -1
- package/dist/tempo/index.js +3 -24
- package/dist/tempo/index.js.map +1 -1
- package/dist/zod/tempo/RpcSchemaTempo.d.ts +46 -2
- package/dist/zod/tempo/RpcSchemaTempo.d.ts.map +1 -1
- package/dist/zod/tempo/TransactionRequest.d.ts +81 -4
- package/dist/zod/tempo/TransactionRequest.d.ts.map +1 -1
- package/dist/zod/tempo/TransactionRequest.js +81 -18
- package/dist/zod/tempo/TransactionRequest.js.map +1 -1
- package/dist/zod/tempo/TxEnvelopeTempo.d.ts +3 -3
- package/dist/zod/tempo/TxEnvelopeTempo.js +1 -1
- package/dist/zod/tempo/TxEnvelopeTempo.js.map +1 -1
- package/dist/zod/tempo/z.d.ts +0 -1
- package/dist/zod/tempo/z.d.ts.map +1 -1
- package/dist/zod/tempo/z.js +0 -1
- package/dist/zod/tempo/z.js.map +1 -1
- package/package.json +1 -11
- package/src/tempo/Channel.test.ts +2 -23
- package/src/tempo/Channel.ts +10 -22
- package/src/tempo/PoolId.test.ts +7 -41
- package/src/tempo/PoolId.ts +14 -10
- package/src/tempo/TransactionRequest.test.ts +174 -1
- package/src/tempo/TransactionRequest.ts +84 -32
- package/src/tempo/TxEnvelopeTempo.test.ts +2 -2
- package/src/tempo/TxEnvelopeTempo.ts +7 -7
- package/src/tempo/index.ts +3 -24
- package/src/version.ts +1 -1
- package/src/zod/tempo/TransactionRequest.ts +86 -20
- package/src/zod/tempo/TxEnvelopeTempo.ts +1 -1
- package/src/zod/tempo/_test/TransactionRequest.test.ts +44 -0
- package/src/zod/tempo/z.ts +0 -1
- package/dist/tempo/TokenId.d.ts +0 -87
- package/dist/tempo/TokenId.d.ts.map +0 -1
- package/dist/tempo/TokenId.js +0 -123
- package/dist/tempo/TokenId.js.map +0 -1
- package/dist/zod/tempo/TokenId.d.ts +0 -6
- package/dist/zod/tempo/TokenId.d.ts.map +0 -1
- package/dist/zod/tempo/TokenId.js +0 -14
- package/dist/zod/tempo/TokenId.js.map +0 -1
- package/src/tempo/TokenId.bench.ts +0 -36
- package/src/tempo/TokenId.test.ts +0 -79
- package/src/tempo/TokenId.ts +0 -141
- package/src/zod/tempo/TokenId.ts +0 -15
- package/src/zod/tempo/_test/TokenId.test-d.ts +0 -17
- package/src/zod/tempo/_test/TokenId.test.ts +0 -21
|
@@ -14,7 +14,6 @@ import * as z from 'zod/mini'
|
|
|
14
14
|
import * as z_AuthorizationTempo from './AuthorizationTempo.js'
|
|
15
15
|
import * as z_KeyAuthorization from './KeyAuthorization.js'
|
|
16
16
|
import * as z_SignatureEnvelope from './SignatureEnvelope.js'
|
|
17
|
-
import * as z_TokenId from './TokenId.js'
|
|
18
17
|
|
|
19
18
|
const fromRpcType = { '0x76': 'tempo' } as const
|
|
20
19
|
const toRpcType = { tempo: '0x76' } as const
|
|
@@ -57,6 +56,16 @@ const CallToRpc = z.object({
|
|
|
57
56
|
value: z.optional(uintBigintNumberish()),
|
|
58
57
|
})
|
|
59
58
|
|
|
59
|
+
const Capabilities = z.record(z.string(), z.unknown())
|
|
60
|
+
|
|
61
|
+
const MultisigInit = z.object({
|
|
62
|
+
salt: z_Hex.Hex,
|
|
63
|
+
threshold: z.number(),
|
|
64
|
+
owners: z.readonly(
|
|
65
|
+
z.array(z.object({ owner: z_Address.Address, weight: z.number() })),
|
|
66
|
+
),
|
|
67
|
+
})
|
|
68
|
+
|
|
60
69
|
/** RPC tempo transaction request schema. */
|
|
61
70
|
export const Rpc = z.object({
|
|
62
71
|
accessList: z.optional(z_AccessList.AccessList),
|
|
@@ -64,6 +73,7 @@ export const Rpc = z.object({
|
|
|
64
73
|
blobVersionedHashes: z.optional(z.readonly(z.array(z_Hex.Hex))),
|
|
65
74
|
blobs: z.optional(z.readonly(z.array(z_Hex.Hex))),
|
|
66
75
|
calls: z.optional(z.readonly(z.array(CallRpc))),
|
|
76
|
+
capabilities: z.optional(Capabilities),
|
|
67
77
|
chainId: z.optional(z_Hex.Hex),
|
|
68
78
|
data: z.optional(z_Hex.Hex),
|
|
69
79
|
feePayer: z.optional(z.boolean()),
|
|
@@ -75,10 +85,13 @@ export const Rpc = z.object({
|
|
|
75
85
|
input: z.optional(z_Hex.Hex),
|
|
76
86
|
keyAuthorization: z.optional(z_KeyAuthorization.Rpc),
|
|
77
87
|
keyData: z.optional(z_Hex.Hex),
|
|
88
|
+
keyId: z.optional(z_Address.Address),
|
|
78
89
|
keyType: z.optional(KeyType),
|
|
79
90
|
maxFeePerBlobGas: z.optional(z_Hex.Hex),
|
|
80
91
|
maxFeePerGas: z.optional(z_Hex.Hex),
|
|
81
92
|
maxPriorityFeePerGas: z.optional(z_Hex.Hex),
|
|
93
|
+
multisigInit: z.optional(MultisigInit),
|
|
94
|
+
multisigSignatureCount: z.optional(z.number()),
|
|
82
95
|
nonce: z.optional(z_Hex.Hex),
|
|
83
96
|
nonceKey: z.optional(z_Hex.Hex),
|
|
84
97
|
r: z.optional(z_Hex.Hex),
|
|
@@ -114,21 +127,25 @@ export const Domain = z.object({
|
|
|
114
127
|
blobVersionedHashes: z.optional(z.readonly(z.array(z_Hex.Hex))),
|
|
115
128
|
blobs: z.optional(z.readonly(z.array(z_Hex.Hex))),
|
|
116
129
|
calls: z.optional(z.readonly(z.array(Call))),
|
|
130
|
+
capabilities: z.optional(Capabilities),
|
|
117
131
|
chainId: z.optional(z.number()),
|
|
118
132
|
data: z.optional(z_Hex.Hex),
|
|
119
133
|
feePayer: z.optional(z.boolean()),
|
|
120
134
|
feePayerSignature: z.optional(z.union([SignatureDecoded, z.null()])),
|
|
121
|
-
feeToken: z.optional(
|
|
135
|
+
feeToken: z.optional(z_Address.Address),
|
|
122
136
|
from: z.optional(z_Address.Address),
|
|
123
137
|
gas: z.optional(z.bigint()),
|
|
124
138
|
gasPrice: z.optional(z.bigint()),
|
|
125
139
|
input: z.optional(z_Hex.Hex),
|
|
126
140
|
keyAuthorization: z.optional(z_KeyAuthorization.Domain),
|
|
127
141
|
keyData: z.optional(z_Hex.Hex),
|
|
142
|
+
keyId: z.optional(z_Address.Address),
|
|
128
143
|
keyType: z.optional(KeyType),
|
|
129
144
|
maxFeePerBlobGas: z.optional(z.bigint()),
|
|
130
145
|
maxFeePerGas: z.optional(z.bigint()),
|
|
131
146
|
maxPriorityFeePerGas: z.optional(z.bigint()),
|
|
147
|
+
multisigInit: z.optional(MultisigInit),
|
|
148
|
+
multisigSignatureCount: z.optional(z.number()),
|
|
132
149
|
nonce: z.optional(z.bigint()),
|
|
133
150
|
nonceKey: z.optional(z.union([z.bigint(), z.literal('random')])),
|
|
134
151
|
r: z.optional(z_Hex.Hex),
|
|
@@ -150,21 +167,25 @@ export const DomainToRpc = z.object({
|
|
|
150
167
|
blobVersionedHashes: z.optional(z.readonly(z.array(z_Hex.Hex))),
|
|
151
168
|
blobs: z.optional(z.readonly(z.array(z_Hex.Hex))),
|
|
152
169
|
calls: z.optional(z.readonly(z.array(CallToRpc))),
|
|
170
|
+
capabilities: z.optional(Capabilities),
|
|
153
171
|
chainId: z.optional(uintNumberNumberish()),
|
|
154
172
|
data: z.optional(z_Hex.Hex),
|
|
155
173
|
feePayer: z.optional(z.boolean()),
|
|
156
174
|
feePayerSignature: z.optional(z.union([SignatureDecoded, z.null()])),
|
|
157
|
-
feeToken: z.optional(
|
|
175
|
+
feeToken: z.optional(z_Address.Address),
|
|
158
176
|
from: z.optional(z_Address.Address),
|
|
159
177
|
gas: z.optional(uintBigintNumberish()),
|
|
160
178
|
gasPrice: z.optional(uintBigintNumberish()),
|
|
161
179
|
input: z.optional(z_Hex.Hex),
|
|
162
180
|
keyAuthorization: z.optional(z_KeyAuthorization.DomainToRpc),
|
|
163
181
|
keyData: z.optional(z_Hex.Hex),
|
|
182
|
+
keyId: z.optional(z_Address.Address),
|
|
164
183
|
keyType: z.optional(KeyType),
|
|
165
184
|
maxFeePerBlobGas: z.optional(uintBigintNumberish()),
|
|
166
185
|
maxFeePerGas: z.optional(uintBigintNumberish()),
|
|
167
186
|
maxPriorityFeePerGas: z.optional(uintBigintNumberish()),
|
|
187
|
+
multisigInit: z.optional(MultisigInit),
|
|
188
|
+
multisigSignatureCount: z.optional(z.number()),
|
|
168
189
|
nonce: z.optional(uintBigintNumberish()),
|
|
169
190
|
nonceKey: z.optional(z.union([uintBigintNumberish(), z.literal('random')])),
|
|
170
191
|
r: z.optional(z_Hex.Hex),
|
|
@@ -232,6 +253,17 @@ function fromRpc(
|
|
|
232
253
|
z_KeyAuthorization.KeyAuthorization,
|
|
233
254
|
request.keyAuthorization as never,
|
|
234
255
|
) as never
|
|
256
|
+
if (typeof request.capabilities !== 'undefined')
|
|
257
|
+
request_.capabilities = request.capabilities
|
|
258
|
+
if (typeof request.feePayer !== 'undefined')
|
|
259
|
+
request_.feePayer = request.feePayer
|
|
260
|
+
if (typeof request.keyData !== 'undefined') request_.keyData = request.keyData
|
|
261
|
+
if (typeof request.keyId !== 'undefined') request_.keyId = request.keyId
|
|
262
|
+
if (typeof request.keyType !== 'undefined') request_.keyType = request.keyType
|
|
263
|
+
if (typeof request.multisigInit !== 'undefined')
|
|
264
|
+
request_.multisigInit = request.multisigInit
|
|
265
|
+
if (typeof request.multisigSignatureCount !== 'undefined')
|
|
266
|
+
request_.multisigSignatureCount = request.multisigSignatureCount
|
|
235
267
|
if (typeof request.validBefore !== 'undefined')
|
|
236
268
|
request_.validBefore = core_Hex.toNumber(request.validBefore)
|
|
237
269
|
if (typeof request.validAfter !== 'undefined')
|
|
@@ -251,6 +283,22 @@ function toRpc(
|
|
|
251
283
|
authorizationList: undefined,
|
|
252
284
|
} as never) as core_TransactionRequest.Rpc
|
|
253
285
|
|
|
286
|
+
const tempo =
|
|
287
|
+
typeof request.calls !== 'undefined' ||
|
|
288
|
+
typeof request.capabilities !== 'undefined' ||
|
|
289
|
+
typeof request.feePayer !== 'undefined' ||
|
|
290
|
+
typeof request.feeToken !== 'undefined' ||
|
|
291
|
+
typeof request.keyAuthorization !== 'undefined' ||
|
|
292
|
+
typeof request.keyData !== 'undefined' ||
|
|
293
|
+
typeof request.keyId !== 'undefined' ||
|
|
294
|
+
typeof request.keyType !== 'undefined' ||
|
|
295
|
+
typeof request.multisigInit !== 'undefined' ||
|
|
296
|
+
typeof request.multisigSignatureCount !== 'undefined' ||
|
|
297
|
+
typeof request.nonceKey !== 'undefined' ||
|
|
298
|
+
typeof request.validBefore !== 'undefined' ||
|
|
299
|
+
typeof request.validAfter !== 'undefined' ||
|
|
300
|
+
request.type === 'tempo'
|
|
301
|
+
|
|
254
302
|
if (request.authorizationList)
|
|
255
303
|
request_rpc.authorizationList = z.encode(
|
|
256
304
|
z_AuthorizationTempo.ListSignedToRpc,
|
|
@@ -269,24 +317,41 @@ function toRpc(
|
|
|
269
317
|
value: call.value ? encodeNumberish(call.value) : '0x',
|
|
270
318
|
data: call.data ?? '0x',
|
|
271
319
|
}))
|
|
272
|
-
else if (request.to || request.data || request.value)
|
|
320
|
+
else if (request.to || request.data || request.value || tempo)
|
|
273
321
|
request_rpc.calls = [
|
|
274
322
|
{
|
|
275
|
-
to:
|
|
323
|
+
to:
|
|
324
|
+
request.to ||
|
|
325
|
+
(tempo && (!request.data || request.data === '0x')
|
|
326
|
+
? '0x0000000000000000000000000000000000000000'
|
|
327
|
+
: undefined),
|
|
276
328
|
value: request.value ? encodeNumberish(request.value) : '0x',
|
|
277
329
|
data: request.data ?? '0x',
|
|
278
330
|
},
|
|
279
331
|
]
|
|
280
|
-
if (
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
332
|
+
if (
|
|
333
|
+
typeof request.feeToken !== 'undefined' &&
|
|
334
|
+
!(request.feePayer === true && !request.feePayerSignature)
|
|
335
|
+
)
|
|
336
|
+
request_rpc.feeToken = request.feeToken
|
|
285
337
|
if (request.keyAuthorization)
|
|
286
338
|
request_rpc.keyAuthorization = z.encode(
|
|
287
339
|
z_KeyAuthorization.KeyAuthorizationToRpc,
|
|
288
340
|
request.keyAuthorization as never,
|
|
289
341
|
) as never
|
|
342
|
+
if (typeof request.capabilities !== 'undefined')
|
|
343
|
+
request_rpc.capabilities = request.capabilities
|
|
344
|
+
if (typeof request.feePayer !== 'undefined')
|
|
345
|
+
request_rpc.feePayer = request.feePayer
|
|
346
|
+
if (typeof request.keyData !== 'undefined')
|
|
347
|
+
request_rpc.keyData = shimKeyData(request.keyData)
|
|
348
|
+
if (typeof request.keyId !== 'undefined') request_rpc.keyId = request.keyId
|
|
349
|
+
if (typeof request.keyType !== 'undefined')
|
|
350
|
+
request_rpc.keyType = request.keyType
|
|
351
|
+
if (typeof request.multisigInit !== 'undefined')
|
|
352
|
+
request_rpc.multisigInit = request.multisigInit
|
|
353
|
+
if (typeof request.multisigSignatureCount !== 'undefined')
|
|
354
|
+
request_rpc.multisigSignatureCount = request.multisigSignatureCount
|
|
290
355
|
if (typeof request.validBefore !== 'undefined')
|
|
291
356
|
request_rpc.validBefore = encodeNumberish(request.validBefore)
|
|
292
357
|
if (typeof request.validAfter !== 'undefined')
|
|
@@ -300,16 +365,7 @@ function toRpc(
|
|
|
300
365
|
})()
|
|
301
366
|
if (nonceKey) request_rpc.nonceKey = nonceKey
|
|
302
367
|
|
|
303
|
-
if (
|
|
304
|
-
typeof request.calls !== 'undefined' ||
|
|
305
|
-
typeof request.feePayer !== 'undefined' ||
|
|
306
|
-
typeof request.feeToken !== 'undefined' ||
|
|
307
|
-
typeof request.keyAuthorization !== 'undefined' ||
|
|
308
|
-
typeof request.nonceKey !== 'undefined' ||
|
|
309
|
-
typeof request.validBefore !== 'undefined' ||
|
|
310
|
-
typeof request.validAfter !== 'undefined' ||
|
|
311
|
-
request.type === 'tempo'
|
|
312
|
-
) {
|
|
368
|
+
if (tempo) {
|
|
313
369
|
request_rpc.type = toRpcType.tempo
|
|
314
370
|
delete request_rpc.data
|
|
315
371
|
delete request_rpc.input
|
|
@@ -320,6 +376,16 @@ function toRpc(
|
|
|
320
376
|
return request_rpc
|
|
321
377
|
}
|
|
322
378
|
|
|
379
|
+
/**
|
|
380
|
+
* Shims key data longer than 4 bytes into a 2-byte big-endian length hint
|
|
381
|
+
* (the node's gas estimator only accepts 1, 2, or 4-byte key data).
|
|
382
|
+
*/
|
|
383
|
+
function shimKeyData(data: core_Hex.Hex): core_Hex.Hex {
|
|
384
|
+
const byteLength = core_Hex.size(data)
|
|
385
|
+
if (byteLength <= 4) return data
|
|
386
|
+
return core_Hex.fromNumber(byteLength, { size: 2 })
|
|
387
|
+
}
|
|
388
|
+
|
|
323
389
|
/** Decodes an RPC signature into a recovered signature. */
|
|
324
390
|
function signatureFromRpc(signature: {
|
|
325
391
|
r: core_Hex.Hex
|
|
@@ -31,7 +31,7 @@ const baseFields = {
|
|
|
31
31
|
calls: z.readonly(z.array(Call)),
|
|
32
32
|
chainId: z.number(),
|
|
33
33
|
feePayerSignature: z.optional(z.union([FeePayerSignature, z.null()])),
|
|
34
|
-
feeToken: z.optional(
|
|
34
|
+
feeToken: z.optional(z_Address.Address),
|
|
35
35
|
from: z.optional(z_Address.Address),
|
|
36
36
|
gas: z.optional(z.bigint()),
|
|
37
37
|
keyAuthorization: z.optional(z_KeyAuthorization.Domain),
|
|
@@ -44,6 +44,50 @@ describe('TransactionRequest', () => {
|
|
|
44
44
|
)
|
|
45
45
|
})
|
|
46
46
|
|
|
47
|
+
test('gas-model hints and capabilities round-trip', () => {
|
|
48
|
+
const hints = {
|
|
49
|
+
capabilities: { balanceDiffs: true },
|
|
50
|
+
keyData: '0x0578',
|
|
51
|
+
keyId: '0xcccccccccccccccccccccccccccccccccccccccc',
|
|
52
|
+
keyType: 'webAuthn',
|
|
53
|
+
multisigInit: {
|
|
54
|
+
salt: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
55
|
+
threshold: 2,
|
|
56
|
+
owners: [
|
|
57
|
+
{
|
|
58
|
+
owner: '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
|
|
59
|
+
weight: 1,
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
owner: '0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',
|
|
63
|
+
weight: 1,
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
multisigSignatureCount: 2,
|
|
68
|
+
} as const
|
|
69
|
+
|
|
70
|
+
const decoded = z.decode(z_TransactionRequest.TransactionRequest, {
|
|
71
|
+
...rpc,
|
|
72
|
+
...hints,
|
|
73
|
+
})
|
|
74
|
+
expect(decoded).toMatchObject(hints)
|
|
75
|
+
|
|
76
|
+
const encoded = z.encode(z_TransactionRequest.TransactionRequest, decoded)
|
|
77
|
+
expect(encoded).toMatchObject(hints)
|
|
78
|
+
expect(encoded).toEqual(core_TransactionRequest.toRpc(decoded))
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
test('feeToken is withheld until the fee payer signs (TIP-76)', () => {
|
|
82
|
+
const decoded = z.decode(z_TransactionRequest.TransactionRequest, rpc)
|
|
83
|
+
const pending = z.encode(z_TransactionRequest.TransactionRequest, {
|
|
84
|
+
...decoded,
|
|
85
|
+
feePayer: true,
|
|
86
|
+
})
|
|
87
|
+
expect(pending.feeToken).toBeUndefined()
|
|
88
|
+
expect(pending.feePayer).toBe(true)
|
|
89
|
+
})
|
|
90
|
+
|
|
47
91
|
test('rejects an invalid request', () => {
|
|
48
92
|
expect(
|
|
49
93
|
z.safeDecode(z_TransactionRequest.TransactionRequest, {
|
package/src/zod/tempo/z.ts
CHANGED
|
@@ -6,7 +6,6 @@ export * as PoolId from './PoolId.js'
|
|
|
6
6
|
export * as RpcSchemaTempo from './RpcSchemaTempo.js'
|
|
7
7
|
export * as SignatureEnvelope from './SignatureEnvelope.js'
|
|
8
8
|
export * as Tick from './Tick.js'
|
|
9
|
-
export * as TokenId from './TokenId.js'
|
|
10
9
|
export * as TokenRole from './TokenRole.js'
|
|
11
10
|
export * as Transaction from './Transaction.js'
|
|
12
11
|
export * as TransactionReceipt from './TransactionReceipt.js'
|
package/dist/tempo/TokenId.d.ts
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import * as Address from '../core/Address.js';
|
|
2
|
-
import * as Hex from '../core/Hex.js';
|
|
3
|
-
export type TokenId = bigint;
|
|
4
|
-
export type TokenIdOrAddress = TokenId | Address.Address;
|
|
5
|
-
/**
|
|
6
|
-
* Converts a token ID or address to a token ID.
|
|
7
|
-
*
|
|
8
|
-
* TIP-20 is Tempo's native token standard for stablecoins with deterministic addresses
|
|
9
|
-
* derived from sequential token IDs (prefix `0x20c0`).
|
|
10
|
-
*
|
|
11
|
-
* [TIP-20 Token Standard](https://docs.tempo.xyz/protocol/tip20/overview)
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* ```ts twoslash
|
|
15
|
-
* import { TokenId } from 'ox/tempo'
|
|
16
|
-
*
|
|
17
|
-
* const tokenId = TokenId.from(1n)
|
|
18
|
-
* ```
|
|
19
|
-
*
|
|
20
|
-
* @param tokenIdOrAddress - The token ID or address.
|
|
21
|
-
* @returns The token ID.
|
|
22
|
-
*/
|
|
23
|
-
export declare function from(tokenIdOrAddress: TokenIdOrAddress | number): TokenId;
|
|
24
|
-
/**
|
|
25
|
-
* Converts a TIP-20 token address to a token ID.
|
|
26
|
-
*
|
|
27
|
-
* [TIP-20 Token Standard](https://docs.tempo.xyz/protocol/tip20/overview)
|
|
28
|
-
*
|
|
29
|
-
* @example
|
|
30
|
-
* ```ts twoslash
|
|
31
|
-
* import { TokenId } from 'ox/tempo'
|
|
32
|
-
*
|
|
33
|
-
* const tokenId = TokenId.fromAddress(
|
|
34
|
-
* '0x20c0000000000000000000000000000000000001'
|
|
35
|
-
* )
|
|
36
|
-
* ```
|
|
37
|
-
*
|
|
38
|
-
* @param address - The token address.
|
|
39
|
-
* @returns The token ID.
|
|
40
|
-
*/
|
|
41
|
-
export declare function fromAddress(address: Address.Address): TokenId;
|
|
42
|
-
/**
|
|
43
|
-
* Converts a TIP-20 token ID to an address.
|
|
44
|
-
*
|
|
45
|
-
* [TIP-20 Token Standard](https://docs.tempo.xyz/protocol/tip20/overview)
|
|
46
|
-
*
|
|
47
|
-
* @example
|
|
48
|
-
* ```ts twoslash
|
|
49
|
-
* import { TokenId } from 'ox/tempo'
|
|
50
|
-
*
|
|
51
|
-
* const address = TokenId.toAddress(1n)
|
|
52
|
-
* ```
|
|
53
|
-
*
|
|
54
|
-
* @param tokenId - The token ID.
|
|
55
|
-
* @returns The address.
|
|
56
|
-
*/
|
|
57
|
-
export declare function toAddress(tokenId: TokenIdOrAddress): Address.Address;
|
|
58
|
-
/**
|
|
59
|
-
* Computes a deterministic TIP-20 token address from a sender address and salt.
|
|
60
|
-
*
|
|
61
|
-
* The address is computed as: `TIP20_PREFIX (12 bytes) || keccak256(abi.encode(sender, salt))[:8]`
|
|
62
|
-
*
|
|
63
|
-
* [TIP-20 Token Standard](https://docs.tempo.xyz/protocol/tip20/overview)
|
|
64
|
-
*
|
|
65
|
-
* @example
|
|
66
|
-
* ```ts twoslash
|
|
67
|
-
* import { TokenId } from 'ox/tempo'
|
|
68
|
-
*
|
|
69
|
-
* const id = TokenId.compute({
|
|
70
|
-
* sender: '0x1234567890123456789012345678901234567890',
|
|
71
|
-
* salt: '0x0000000000000000000000000000000000000000000000000000000000000001'
|
|
72
|
-
* })
|
|
73
|
-
* ```
|
|
74
|
-
*
|
|
75
|
-
* @param value - The sender address and salt.
|
|
76
|
-
* @returns The computed TIP-20 token id.
|
|
77
|
-
*/
|
|
78
|
-
export declare function compute(value: compute.Value): bigint;
|
|
79
|
-
export declare namespace compute {
|
|
80
|
-
type Value = {
|
|
81
|
-
/** The salt (32 bytes). */
|
|
82
|
-
salt: Hex.Hex;
|
|
83
|
-
/** The sender address. */
|
|
84
|
-
sender: Address.Address;
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
//# sourceMappingURL=TokenId.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TokenId.d.ts","sourceRoot":"","sources":["../../src/tempo/TokenId.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,OAAO,MAAM,oBAAoB,CAAA;AAE7C,OAAO,KAAK,GAAG,MAAM,gBAAgB,CAAA;AAIrC,MAAM,MAAM,OAAO,GAAG,MAAM,CAAA;AAC5B,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAA;AAExD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,IAAI,CAAC,gBAAgB,EAAE,gBAAgB,GAAG,MAAM,GAAG,OAAO,CAOzE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,GAAG,OAAO,CAiB7D;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAQpE;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,GAAG,MAAM,CAapD;AAED,MAAM,CAAC,OAAO,WAAW,OAAO,CAAC;IAC/B,KAAY,KAAK,GAAG;QAClB,2BAA2B;QAC3B,IAAI,EAAE,GAAG,CAAC,GAAG,CAAA;QACb,0BAA0B;QAC1B,MAAM,EAAE,OAAO,CAAC,OAAO,CAAA;KACxB,CAAA;CACF"}
|
package/dist/tempo/TokenId.js
DELETED
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
import { keccak_256 } from '@noble/hashes/sha3.js';
|
|
2
|
-
import * as Address from '../core/Address.js';
|
|
3
|
-
import * as Bytes from '../core/Bytes.js';
|
|
4
|
-
import * as Hex from '../core/Hex.js';
|
|
5
|
-
const tip20Prefix = '0x20c0';
|
|
6
|
-
/**
|
|
7
|
-
* Converts a token ID or address to a token ID.
|
|
8
|
-
*
|
|
9
|
-
* TIP-20 is Tempo's native token standard for stablecoins with deterministic addresses
|
|
10
|
-
* derived from sequential token IDs (prefix `0x20c0`).
|
|
11
|
-
*
|
|
12
|
-
* [TIP-20 Token Standard](https://docs.tempo.xyz/protocol/tip20/overview)
|
|
13
|
-
*
|
|
14
|
-
* @example
|
|
15
|
-
* ```ts twoslash
|
|
16
|
-
* import { TokenId } from 'ox/tempo'
|
|
17
|
-
*
|
|
18
|
-
* const tokenId = TokenId.from(1n)
|
|
19
|
-
* ```
|
|
20
|
-
*
|
|
21
|
-
* @param tokenIdOrAddress - The token ID or address.
|
|
22
|
-
* @returns The token ID.
|
|
23
|
-
*/
|
|
24
|
-
export function from(tokenIdOrAddress) {
|
|
25
|
-
if (typeof tokenIdOrAddress === 'bigint' ||
|
|
26
|
-
typeof tokenIdOrAddress === 'number')
|
|
27
|
-
return BigInt(tokenIdOrAddress);
|
|
28
|
-
return fromAddress(tokenIdOrAddress);
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Converts a TIP-20 token address to a token ID.
|
|
32
|
-
*
|
|
33
|
-
* [TIP-20 Token Standard](https://docs.tempo.xyz/protocol/tip20/overview)
|
|
34
|
-
*
|
|
35
|
-
* @example
|
|
36
|
-
* ```ts twoslash
|
|
37
|
-
* import { TokenId } from 'ox/tempo'
|
|
38
|
-
*
|
|
39
|
-
* const tokenId = TokenId.fromAddress(
|
|
40
|
-
* '0x20c0000000000000000000000000000000000001'
|
|
41
|
-
* )
|
|
42
|
-
* ```
|
|
43
|
-
*
|
|
44
|
-
* @param address - The token address.
|
|
45
|
-
* @returns The token ID.
|
|
46
|
-
*/
|
|
47
|
-
export function fromAddress(address) {
|
|
48
|
-
const resolved = address;
|
|
49
|
-
// The TIP-20 prefix check is case-insensitive, but most inputs are already
|
|
50
|
-
// lowercase, so peek the prefix bytes before falling back to a full
|
|
51
|
-
// `.toLowerCase()`.
|
|
52
|
-
const c2 = resolved.charCodeAt(2);
|
|
53
|
-
const c3 = resolved.charCodeAt(3);
|
|
54
|
-
const c4 = resolved.charCodeAt(4);
|
|
55
|
-
const c5 = resolved.charCodeAt(5);
|
|
56
|
-
const isPrefix = c2 === 50 /* '2' */ &&
|
|
57
|
-
c3 === 48 /* '0' */ &&
|
|
58
|
-
(c4 === 99 || c4 === 67) /* 'c' or 'C' */ &&
|
|
59
|
-
c5 === 48; /* '0' */
|
|
60
|
-
if (!isPrefix)
|
|
61
|
-
throw new Error('invalid tip20 address.');
|
|
62
|
-
// The trailing 36 hex characters encode the token id big-endian.
|
|
63
|
-
return BigInt(`0x${resolved.slice(tip20Prefix.length)}`);
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Converts a TIP-20 token ID to an address.
|
|
67
|
-
*
|
|
68
|
-
* [TIP-20 Token Standard](https://docs.tempo.xyz/protocol/tip20/overview)
|
|
69
|
-
*
|
|
70
|
-
* @example
|
|
71
|
-
* ```ts twoslash
|
|
72
|
-
* import { TokenId } from 'ox/tempo'
|
|
73
|
-
*
|
|
74
|
-
* const address = TokenId.toAddress(1n)
|
|
75
|
-
* ```
|
|
76
|
-
*
|
|
77
|
-
* @param tokenId - The token ID.
|
|
78
|
-
* @returns The address.
|
|
79
|
-
*/
|
|
80
|
-
export function toAddress(tokenId) {
|
|
81
|
-
if (typeof tokenId === 'string') {
|
|
82
|
-
Address.assert(tokenId);
|
|
83
|
-
return tokenId;
|
|
84
|
-
}
|
|
85
|
-
const tokenIdHex = Hex.fromNumber(tokenId, { size: 18 });
|
|
86
|
-
return Hex.concat(tip20Prefix, tokenIdHex);
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Computes a deterministic TIP-20 token address from a sender address and salt.
|
|
90
|
-
*
|
|
91
|
-
* The address is computed as: `TIP20_PREFIX (12 bytes) || keccak256(abi.encode(sender, salt))[:8]`
|
|
92
|
-
*
|
|
93
|
-
* [TIP-20 Token Standard](https://docs.tempo.xyz/protocol/tip20/overview)
|
|
94
|
-
*
|
|
95
|
-
* @example
|
|
96
|
-
* ```ts twoslash
|
|
97
|
-
* import { TokenId } from 'ox/tempo'
|
|
98
|
-
*
|
|
99
|
-
* const id = TokenId.compute({
|
|
100
|
-
* sender: '0x1234567890123456789012345678901234567890',
|
|
101
|
-
* salt: '0x0000000000000000000000000000000000000000000000000000000000000001'
|
|
102
|
-
* })
|
|
103
|
-
* ```
|
|
104
|
-
*
|
|
105
|
-
* @param value - The sender address and salt.
|
|
106
|
-
* @returns The computed TIP-20 token id.
|
|
107
|
-
*/
|
|
108
|
-
export function compute(value) {
|
|
109
|
-
// ABI encoding of (address, bytes32) is the 32-byte left-padded address
|
|
110
|
-
// followed by the 32-byte salt. Build that 64-byte buffer directly and hash
|
|
111
|
-
// it, instead of round-tripping through `AbiParameters.encode`.
|
|
112
|
-
const buffer = new Uint8Array(64);
|
|
113
|
-
const addressBytes = Bytes.fromHex(value.sender);
|
|
114
|
-
buffer.set(addressBytes, 12);
|
|
115
|
-
buffer.set(Bytes.fromHex(value.salt, { size: 32 }), 32);
|
|
116
|
-
const hash = keccak_256(buffer);
|
|
117
|
-
// First 8 bytes of the digest, big-endian.
|
|
118
|
-
let id = 0n;
|
|
119
|
-
for (let i = 0; i < 8; i++)
|
|
120
|
-
id = (id << 8n) | BigInt(hash[i]);
|
|
121
|
-
return id;
|
|
122
|
-
}
|
|
123
|
-
//# sourceMappingURL=TokenId.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TokenId.js","sourceRoot":"","sources":["../../src/tempo/TokenId.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import * as z from 'zod/mini';
|
|
2
|
-
/** TIP-20 token id schema (non-negative bigint). */
|
|
3
|
-
export declare const TokenId: z.ZodMiniBigInt<bigint>;
|
|
4
|
-
/** Codec decoding a TIP-20 token address into a token id. */
|
|
5
|
-
export declare const address: z.ZodMiniCodec<z.ZodMiniTemplateLiteral<`0x${string}`>, z.ZodMiniBigInt<bigint>>;
|
|
6
|
-
//# sourceMappingURL=TokenId.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TokenId.d.ts","sourceRoot":"","sources":["../../../src/zod/tempo/TokenId.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,CAAC,MAAM,UAAU,CAAA;AAE7B,oDAAoD;AACpD,eAAO,MAAM,OAAO,yBAE2C,CAAA;AAE/D,6DAA6D;AAC7D,eAAO,MAAM,OAAO,kFAGlB,CAAA"}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/* eslint-disable jsdoc-js/require-jsdoc, jsdoc-js/require-description, jsdoc-js/require-example */
|
|
2
|
-
import * as core_TokenId from '../../tempo/TokenId.js';
|
|
3
|
-
import * as z_Address from '../Address.js';
|
|
4
|
-
import * as z from 'zod/mini';
|
|
5
|
-
/** TIP-20 token id schema (non-negative bigint). */
|
|
6
|
-
export const TokenId = z
|
|
7
|
-
.bigint()
|
|
8
|
-
.check(z.refine((value) => value >= 0n, 'expected token id'));
|
|
9
|
-
/** Codec decoding a TIP-20 token address into a token id. */
|
|
10
|
-
export const address = z.codec(z_Address.Address, TokenId, {
|
|
11
|
-
decode: (value) => core_TokenId.fromAddress(value),
|
|
12
|
-
encode: (value) => core_TokenId.toAddress(value),
|
|
13
|
-
});
|
|
14
|
-
//# sourceMappingURL=TokenId.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TokenId.js","sourceRoot":"","sources":["../../../src/zod/tempo/TokenId.ts"],"names":[],"mappings":"AAAA,mGAAmG;AACnG,OAAO,KAAK,YAAY,MAAM,wBAAwB,CAAA;AACtD,OAAO,KAAK,SAAS,MAAM,eAAe,CAAA;AAC1C,OAAO,KAAK,CAAC,MAAM,UAAU,CAAA;AAE7B,oDAAoD;AACpD,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC;KACrB,MAAM,EAAE;KACR,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE,EAAE,mBAAmB,CAAC,CAAC,CAAA;AAE/D,6DAA6D;AAC7D,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE;IACzD,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,WAAW,CAAC,KAAK,CAAC;IAClD,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,KAAK,CAAC;CACjD,CAAC,CAAA"}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { bench, describe } from 'vp/test'
|
|
2
|
-
import * as TokenId from './TokenId.js'
|
|
3
|
-
|
|
4
|
-
const sender = '0x1234567890123456789012345678901234567890' as const
|
|
5
|
-
const salt =
|
|
6
|
-
'0x0000000000000000000000000000000000000000000000000000000000000001' as const
|
|
7
|
-
|
|
8
|
-
const tokenIdAddress = '0x20c0000000000000000000000000000000000001' as const
|
|
9
|
-
const tokenIdBigInt = 1n
|
|
10
|
-
const tokenIdLargeBigInt = 0xdeadbeefcafebabe1234n
|
|
11
|
-
|
|
12
|
-
describe('TokenId.compute', () => {
|
|
13
|
-
bench('hex sender', () => {
|
|
14
|
-
TokenId.compute({ sender, salt })
|
|
15
|
-
})
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
describe('TokenId.fromAddress', () => {
|
|
19
|
-
bench('hex address', () => {
|
|
20
|
-
TokenId.fromAddress(tokenIdAddress)
|
|
21
|
-
})
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
describe('TokenId.toAddress', () => {
|
|
25
|
-
bench('small bigint', () => {
|
|
26
|
-
TokenId.toAddress(tokenIdBigInt)
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
bench('large bigint', () => {
|
|
30
|
-
TokenId.toAddress(tokenIdLargeBigInt)
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
bench('hex address passthrough', () => {
|
|
34
|
-
TokenId.toAddress(tokenIdAddress)
|
|
35
|
-
})
|
|
36
|
-
})
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import { Hex } from 'ox'
|
|
2
|
-
import { TokenId } from 'ox/tempo'
|
|
3
|
-
import { expect, test } from 'vp/test'
|
|
4
|
-
|
|
5
|
-
test('from', () => {
|
|
6
|
-
expect(TokenId.from(0n)).toBe(0n)
|
|
7
|
-
expect(TokenId.from(0x1)).toBe(1n)
|
|
8
|
-
expect(TokenId.from(0xdef)).toBe(0xdefn)
|
|
9
|
-
expect(TokenId.from('0x20c0000000000000000000000000000000000000')).toBe(0n)
|
|
10
|
-
expect(TokenId.from('0x20c0000000000000000000000000000000000001')).toBe(1n)
|
|
11
|
-
expect(TokenId.from('0x20c0000000000000000000000000000000000def')).toBe(
|
|
12
|
-
0xdefn,
|
|
13
|
-
)
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
test('fromAddress', () => {
|
|
17
|
-
expect(
|
|
18
|
-
TokenId.fromAddress('0x20c0000000000000000000000000000000000000'),
|
|
19
|
-
).toBe(0n)
|
|
20
|
-
expect(
|
|
21
|
-
TokenId.fromAddress('0x20c0000000000000000000000000000000000001'),
|
|
22
|
-
).toBe(1n)
|
|
23
|
-
expect(
|
|
24
|
-
TokenId.fromAddress('0x20c0000000000000000000000000000000000def'),
|
|
25
|
-
).toBe(0xdefn)
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
test('toAddress', () => {
|
|
29
|
-
expect(TokenId.toAddress(0n)).toBe(
|
|
30
|
-
'0x20c0000000000000000000000000000000000000',
|
|
31
|
-
)
|
|
32
|
-
expect(TokenId.toAddress('0x20c0000000000000000000000000000000000000')).toBe(
|
|
33
|
-
'0x20c0000000000000000000000000000000000000',
|
|
34
|
-
)
|
|
35
|
-
expect(TokenId.toAddress(1n)).toBe(
|
|
36
|
-
'0x20c0000000000000000000000000000000000001',
|
|
37
|
-
)
|
|
38
|
-
expect(TokenId.toAddress(0xdefn)).toBe(
|
|
39
|
-
'0x20c0000000000000000000000000000000000def',
|
|
40
|
-
)
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
test('compute', () => {
|
|
44
|
-
const sender = '0x1234567890123456789012345678901234567890'
|
|
45
|
-
const salt1 =
|
|
46
|
-
'0x0000000000000000000000000000000000000000000000000000000000000001'
|
|
47
|
-
const salt2 =
|
|
48
|
-
'0x0000000000000000000000000000000000000000000000000000000000000002'
|
|
49
|
-
|
|
50
|
-
const id1 = TokenId.compute({ sender, salt: salt1 })
|
|
51
|
-
const id2 = TokenId.compute({ sender, salt: salt2 })
|
|
52
|
-
const address1 = TokenId.toAddress(id1)
|
|
53
|
-
const address2 = TokenId.toAddress(id2)
|
|
54
|
-
|
|
55
|
-
// deterministic: same inputs produce same output
|
|
56
|
-
expect(TokenId.compute({ sender, salt: salt1 })).toBe(id1)
|
|
57
|
-
|
|
58
|
-
// different salts produce different addresses
|
|
59
|
-
expect(address1).not.toBe(address2)
|
|
60
|
-
|
|
61
|
-
// address suffix matches id
|
|
62
|
-
expect(Hex.slice(address1, 12)).toBe(Hex.fromNumber(id1, { size: 8 }))
|
|
63
|
-
|
|
64
|
-
// addresses have TIP-20 prefix (0x20c0 followed by zeroes for 12 bytes total)
|
|
65
|
-
expect(address1.toLowerCase().startsWith('0x20c000000000000000000000')).toBe(
|
|
66
|
-
true,
|
|
67
|
-
)
|
|
68
|
-
expect(address2.toLowerCase().startsWith('0x20c000000000000000000000')).toBe(
|
|
69
|
-
true,
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
// addresses are 20 bytes (40 hex chars + 0x prefix)
|
|
73
|
-
expect(address1.length).toBe(42)
|
|
74
|
-
|
|
75
|
-
// different senders produce different addresses
|
|
76
|
-
const otherSender = '0xabcdefabcdefabcdefabcdefabcdefabcdefabcd'
|
|
77
|
-
const address3 = TokenId.compute({ sender: otherSender, salt: salt1 })
|
|
78
|
-
expect(address3).not.toBe(address1)
|
|
79
|
-
})
|