ox 1.7.4 → 1.8.0
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 +22 -0
- package/dist/core/AbiEvent.d.ts.map +1 -1
- package/dist/core/AbiEvent.js +10 -9
- package/dist/core/AbiEvent.js.map +1 -1
- package/dist/core/Blobs.d.ts.map +1 -1
- package/dist/core/Blobs.js +6 -2
- package/dist/core/Blobs.js.map +1 -1
- package/dist/core/Frame.d.ts +290 -0
- package/dist/core/Frame.d.ts.map +1 -0
- package/dist/core/Frame.js +306 -0
- package/dist/core/Frame.js.map +1 -0
- package/dist/core/FrameReceipt.d.ts +92 -0
- package/dist/core/FrameReceipt.d.ts.map +1 -0
- package/dist/core/FrameReceipt.js +72 -0
- package/dist/core/FrameReceipt.js.map +1 -0
- package/dist/core/FrameSignature.d.ts +357 -0
- package/dist/core/FrameSignature.d.ts.map +1 -0
- package/dist/core/FrameSignature.js +411 -0
- package/dist/core/FrameSignature.js.map +1 -0
- package/dist/core/Signature.d.ts +6 -5
- package/dist/core/Signature.d.ts.map +1 -1
- package/dist/core/Signature.js +17 -7
- package/dist/core/Signature.js.map +1 -1
- package/dist/core/Siwe.d.ts.map +1 -1
- package/dist/core/Siwe.js +21 -1
- package/dist/core/Siwe.js.map +1 -1
- package/dist/core/Transaction.d.ts +29 -4
- package/dist/core/Transaction.d.ts.map +1 -1
- package/dist/core/Transaction.js +25 -4
- package/dist/core/Transaction.js.map +1 -1
- package/dist/core/TransactionReceipt.d.ts +13 -4
- package/dist/core/TransactionReceipt.d.ts.map +1 -1
- package/dist/core/TransactionReceipt.js +14 -0
- package/dist/core/TransactionReceipt.js.map +1 -1
- package/dist/core/TransactionRequest.d.ts +15 -7
- package/dist/core/TransactionRequest.d.ts.map +1 -1
- package/dist/core/TransactionRequest.js +47 -1
- package/dist/core/TransactionRequest.js.map +1 -1
- package/dist/core/TxEnvelope.d.ts +35 -21
- package/dist/core/TxEnvelope.d.ts.map +1 -1
- package/dist/core/TxEnvelope.js +46 -6
- package/dist/core/TxEnvelope.js.map +1 -1
- package/dist/core/TxEnvelopeEip8141.d.ts +341 -0
- package/dist/core/TxEnvelopeEip8141.d.ts.map +1 -0
- package/dist/core/TxEnvelopeEip8141.js +485 -0
- package/dist/core/TxEnvelopeEip8141.js.map +1 -0
- package/dist/core/internal/curves.d.ts +2 -0
- package/dist/core/internal/curves.d.ts.map +1 -1
- package/dist/core/internal/curves.js +2 -0
- package/dist/core/internal/curves.js.map +1 -1
- package/dist/index.d.ts +73 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +73 -0
- package/dist/index.js.map +1 -1
- package/dist/tempo/KeyAuthorization.d.ts +42 -38
- package/dist/tempo/KeyAuthorization.d.ts.map +1 -1
- package/dist/tempo/KeyAuthorization.js +24 -4
- package/dist/tempo/KeyAuthorization.js.map +1 -1
- package/dist/tempo/MultisigConfig.d.ts +18 -15
- package/dist/tempo/MultisigConfig.d.ts.map +1 -1
- package/dist/tempo/MultisigConfig.js +49 -20
- package/dist/tempo/MultisigConfig.js.map +1 -1
- package/dist/tempo/MultisigOperation.d.ts +3 -2
- package/dist/tempo/MultisigOperation.d.ts.map +1 -1
- package/dist/tempo/MultisigOperation.js +20 -100
- package/dist/tempo/MultisigOperation.js.map +1 -1
- package/dist/tempo/MultisigSimulation.d.ts +2 -49
- package/dist/tempo/MultisigSimulation.d.ts.map +1 -1
- package/dist/tempo/MultisigSimulation.js +18 -46
- package/dist/tempo/MultisigSimulation.js.map +1 -1
- package/dist/tempo/SignatureEnvelope.d.ts +72 -140
- package/dist/tempo/SignatureEnvelope.d.ts.map +1 -1
- package/dist/tempo/SignatureEnvelope.js +130 -181
- package/dist/tempo/SignatureEnvelope.js.map +1 -1
- package/dist/tempo/Transaction.d.ts +2 -0
- package/dist/tempo/Transaction.d.ts.map +1 -1
- package/dist/tempo/TransactionReceipt.d.ts +2 -0
- package/dist/tempo/TransactionReceipt.d.ts.map +1 -1
- package/dist/tempo/TransactionRequest.d.ts +4 -2
- package/dist/tempo/TransactionRequest.d.ts.map +1 -1
- package/dist/tempo/TransactionRequest.js +6 -1
- package/dist/tempo/TransactionRequest.js.map +1 -1
- package/dist/tempo/index.d.ts +3 -1
- package/dist/tempo/index.d.ts.map +1 -1
- package/dist/tempo/index.js +3 -1
- package/dist/tempo/index.js.map +1 -1
- package/dist/zod/Block.d.ts +123 -0
- package/dist/zod/Block.d.ts.map +1 -1
- package/dist/zod/Frame.d.ts +73 -0
- package/dist/zod/Frame.d.ts.map +1 -0
- package/dist/zod/Frame.js +74 -0
- package/dist/zod/Frame.js.map +1 -0
- package/dist/zod/FrameReceipt.d.ts +50 -0
- package/dist/zod/FrameReceipt.d.ts.map +1 -0
- package/dist/zod/FrameReceipt.js +37 -0
- package/dist/zod/FrameReceipt.js.map +1 -0
- package/dist/zod/FrameSignature.d.ts +63 -0
- package/dist/zod/FrameSignature.d.ts.map +1 -0
- package/dist/zod/FrameSignature.js +66 -0
- package/dist/zod/FrameSignature.js.map +1 -0
- package/dist/zod/RpcSchema.d.ts +806 -11
- package/dist/zod/RpcSchema.d.ts.map +1 -1
- package/dist/zod/Transaction.d.ts +252 -0
- package/dist/zod/Transaction.d.ts.map +1 -1
- package/dist/zod/Transaction.js +54 -0
- package/dist/zod/Transaction.js.map +1 -1
- package/dist/zod/TransactionEnvelope.d.ts +233 -4
- package/dist/zod/TransactionEnvelope.d.ts.map +1 -1
- package/dist/zod/TransactionEnvelope.js +9 -0
- package/dist/zod/TransactionEnvelope.js.map +1 -1
- package/dist/zod/TransactionReceipt.d.ts +48 -0
- package/dist/zod/TransactionReceipt.d.ts.map +1 -1
- package/dist/zod/TransactionReceipt.js +8 -3
- package/dist/zod/TransactionReceipt.js.map +1 -1
- package/dist/zod/TransactionRequest.d.ts +50 -2
- package/dist/zod/TransactionRequest.d.ts.map +1 -1
- package/dist/zod/TransactionRequest.js +10 -4
- package/dist/zod/TransactionRequest.js.map +1 -1
- package/dist/zod/TxEnvelopeEip8141.d.ts +166 -0
- package/dist/zod/TxEnvelopeEip8141.d.ts.map +1 -0
- package/dist/zod/TxEnvelopeEip8141.js +76 -0
- package/dist/zod/TxEnvelopeEip8141.js.map +1 -0
- package/dist/zod/internal/Frame.d.ts +4 -0
- package/dist/zod/internal/Frame.d.ts.map +1 -0
- package/dist/zod/internal/Frame.js +17 -0
- package/dist/zod/internal/Frame.js.map +1 -0
- package/dist/zod/internal/rpcSchemas/Eth.d.ts +842 -11
- package/dist/zod/internal/rpcSchemas/Eth.d.ts.map +1 -1
- package/dist/zod/internal/rpcSchemas/Wallet.d.ts +56 -2
- package/dist/zod/internal/rpcSchemas/Wallet.d.ts.map +1 -1
- package/dist/zod/tempo/AuthorizationTempo.d.ts +350 -10
- package/dist/zod/tempo/AuthorizationTempo.d.ts.map +1 -1
- package/dist/zod/tempo/KeyAuthorization.d.ts +242 -422
- package/dist/zod/tempo/KeyAuthorization.d.ts.map +1 -1
- package/dist/zod/tempo/KeyAuthorization.js +29 -31
- package/dist/zod/tempo/KeyAuthorization.js.map +1 -1
- package/dist/zod/tempo/MultisigSimulation.d.ts +8 -76
- package/dist/zod/tempo/MultisigSimulation.d.ts.map +1 -1
- package/dist/zod/tempo/MultisigSimulation.js +3 -37
- package/dist/zod/tempo/MultisigSimulation.js.map +1 -1
- package/dist/zod/tempo/RpcSchemaTempo.d.ts +424 -228
- package/dist/zod/tempo/RpcSchemaTempo.d.ts.map +1 -1
- package/dist/zod/tempo/SignatureEnvelope.d.ts +105 -3
- package/dist/zod/tempo/SignatureEnvelope.d.ts.map +1 -1
- package/dist/zod/tempo/SignatureEnvelope.js +21 -9
- package/dist/zod/tempo/SignatureEnvelope.js.map +1 -1
- package/dist/zod/tempo/Transaction.d.ts +783 -432
- package/dist/zod/tempo/Transaction.d.ts.map +1 -1
- package/dist/zod/tempo/TransactionRequest.d.ts +590 -473
- package/dist/zod/tempo/TransactionRequest.d.ts.map +1 -1
- package/dist/zod/tempo/TransactionRequest.js +8 -0
- package/dist/zod/tempo/TransactionRequest.js.map +1 -1
- package/dist/zod/tempo/TxEnvelopeTempo.d.ts +327 -213
- package/dist/zod/tempo/TxEnvelopeTempo.d.ts.map +1 -1
- package/dist/zod/tempo/ZoneRpcAuthentication.d.ts +105 -3
- package/dist/zod/tempo/ZoneRpcAuthentication.d.ts.map +1 -1
- package/dist/zod/z.d.ts +4 -0
- package/dist/zod/z.d.ts.map +1 -1
- package/dist/zod/z.js +4 -0
- package/dist/zod/z.js.map +1 -1
- package/package.json +41 -1
- package/src/core/AbiEvent.ts +11 -9
- package/src/core/Blobs.ts +6 -2
- package/src/core/Frame.ts +443 -0
- package/src/core/FrameReceipt.ts +117 -0
- package/src/core/FrameSignature.ts +593 -0
- package/src/core/Signature.ts +41 -11
- package/src/core/Siwe.ts +20 -1
- package/src/core/Transaction.ts +82 -5
- package/src/core/TransactionReceipt.ts +41 -3
- package/src/core/TransactionRequest.ts +71 -4
- package/src/core/TxEnvelope.ts +159 -90
- package/src/core/TxEnvelopeEip8141.ts +715 -0
- package/src/core/_test/AbiEvent.test.ts +45 -0
- package/src/core/_test/Blobs.test.ts +22 -0
- package/src/core/_test/Frame.test-d.ts +96 -0
- package/src/core/_test/Frame.test.ts +267 -0
- package/src/core/_test/FrameReceipt.test.ts +86 -0
- package/src/core/_test/FrameSignature.test-d.ts +93 -0
- package/src/core/_test/FrameSignature.test.ts +554 -0
- package/src/core/_test/Signature.test.ts +166 -0
- package/src/core/_test/Siwe.test.ts +100 -1
- package/src/core/_test/Transaction.test.ts +33 -0
- package/src/core/_test/TransactionEnvelope.test-d.ts +74 -0
- package/src/core/_test/TransactionEnvelope.test.ts +107 -0
- package/src/core/_test/TransactionReceipt.test.ts +59 -0
- package/src/core/_test/TransactionRequest.test-d.ts +50 -0
- package/src/core/_test/TransactionRequest.test.ts +88 -1
- package/src/core/_test/TxEnvelopeEip8141.test-d.ts +44 -0
- package/src/core/_test/TxEnvelopeEip8141.test.ts +1775 -0
- package/src/core/_test/curves.test.ts +6 -1
- package/src/core/_test/index.test.ts +4 -0
- package/src/core/internal/curves.ts +4 -0
- package/src/index.ts +77 -0
- package/src/tempo/AuthorizationTempo.test.ts +8 -4
- package/src/tempo/KeyAuthorization.test-d.ts +16 -63
- package/src/tempo/KeyAuthorization.test.ts +69 -11
- package/src/tempo/KeyAuthorization.ts +107 -63
- package/src/tempo/MultisigConfig.test.ts +44 -20
- package/src/tempo/MultisigConfig.ts +65 -23
- package/src/tempo/MultisigOperation.test.ts +79 -550
- package/src/tempo/MultisigOperation.ts +31 -146
- package/src/tempo/MultisigSimulation.test-d.ts +2 -2
- package/src/tempo/MultisigSimulation.test.ts +21 -110
- package/src/tempo/MultisigSimulation.ts +25 -99
- package/src/tempo/SignatureEnvelope.test-d.ts +29 -47
- package/src/tempo/SignatureEnvelope.test.ts +328 -541
- package/src/tempo/SignatureEnvelope.ts +196 -291
- package/src/tempo/Transaction.test.ts +4 -4
- package/src/tempo/TransactionRequest.test.ts +17 -80
- package/src/tempo/TransactionRequest.ts +19 -2
- package/src/tempo/index.ts +3 -1
- package/src/tempo/multisig.e2e.test.ts +321 -860
- package/src/version.ts +1 -1
- package/src/zod/Frame.ts +82 -0
- package/src/zod/FrameReceipt.ts +48 -0
- package/src/zod/FrameSignature.ts +78 -0
- package/src/zod/Transaction.ts +63 -0
- package/src/zod/TransactionEnvelope.ts +33 -0
- package/src/zod/TransactionReceipt.ts +14 -3
- package/src/zod/TransactionRequest.ts +18 -3
- package/src/zod/TxEnvelopeEip8141.ts +102 -0
- package/src/zod/_test/Frame.test-d.ts +41 -0
- package/src/zod/_test/Frame.test.ts +54 -0
- package/src/zod/_test/FrameReceipt.test.ts +75 -0
- package/src/zod/_test/FrameSignature.test.ts +94 -0
- package/src/zod/_test/TxEnvelopeEip8141.test.ts +116 -0
- package/src/zod/internal/Frame.ts +26 -0
- package/src/zod/tempo/KeyAuthorization.ts +50 -39
- package/src/zod/tempo/MultisigSimulation.ts +3 -48
- package/src/zod/tempo/SignatureEnvelope.ts +46 -35
- package/src/zod/tempo/TransactionRequest.ts +14 -0
- package/src/zod/tempo/_test/KeyAuthorization.test.ts +69 -20
- package/src/zod/tempo/_test/MultisigSimulation.test.ts +6 -31
- package/src/zod/tempo/_test/SignatureEnvelope.test.ts +118 -85
- package/src/zod/tempo/_test/TransactionRequest.test.ts +9 -19
- package/src/zod/z.ts +4 -0
|
@@ -572,6 +572,172 @@ describe('toBytes', () => {
|
|
|
572
572
|
})
|
|
573
573
|
})
|
|
574
574
|
|
|
575
|
+
describe('toCompactBytes', () => {
|
|
576
|
+
test('default', () => {
|
|
577
|
+
const bytes = Signature.toCompactBytes({
|
|
578
|
+
r: '0x6e100a352ec6ad1b70802290e18aeed190704973570f3b8ed42cb9808e2ea6bf',
|
|
579
|
+
s: '0x4a90a229a244495b41890987806fcbd2d5d23fc0dbe5f5256c2613c039d76db8',
|
|
580
|
+
yParity: 1,
|
|
581
|
+
})
|
|
582
|
+
expect(bytes.length).toBe(64)
|
|
583
|
+
expect(Hex.fromBytes(bytes)).toBe(
|
|
584
|
+
'0x6e100a352ec6ad1b70802290e18aeed190704973570f3b8ed42cb9808e2ea6bf4a90a229a244495b41890987806fcbd2d5d23fc0dbe5f5256c2613c039d76db8',
|
|
585
|
+
)
|
|
586
|
+
})
|
|
587
|
+
|
|
588
|
+
test('behavior: r/s shorter than 32 bytes are left-padded, not right-padded', () => {
|
|
589
|
+
const bytes = Signature.toCompactBytes({
|
|
590
|
+
r: '0x01',
|
|
591
|
+
s: '0x02',
|
|
592
|
+
yParity: 0,
|
|
593
|
+
})
|
|
594
|
+
// `r` occupies the first 32 bytes and must be the big-endian integer `1`
|
|
595
|
+
// (left-padded), not `1` shifted into the top byte (right-padded).
|
|
596
|
+
expect(Hex.fromBytes(bytes.subarray(0, 32))).toBe(
|
|
597
|
+
'0x0000000000000000000000000000000000000000000000000000000000000001',
|
|
598
|
+
)
|
|
599
|
+
expect(Hex.fromBytes(bytes.subarray(32, 64))).toBe(
|
|
600
|
+
'0x0000000000000000000000000000000000000000000000000000000000000002',
|
|
601
|
+
)
|
|
602
|
+
})
|
|
603
|
+
|
|
604
|
+
test('behavior: round-trips through recoverPublicKey for a signature whose r has a leading zero byte', async () => {
|
|
605
|
+
const { Secp256k1 } = await import('ox')
|
|
606
|
+
const payload = `0x${'11'.repeat(32)}` as const
|
|
607
|
+
const privateKey = Hex.fromNumber(4n * 123456789013n + 7n, { size: 32 })
|
|
608
|
+
const signature = Secp256k1.sign({ payload, privateKey })
|
|
609
|
+
// sanity: this fixture's `r` genuinely has a leading zero byte
|
|
610
|
+
expect(signature.r.startsWith('0x00')).toBe(true)
|
|
611
|
+
const expectedPublicKey = Secp256k1.recoverPublicKey({ payload, signature })
|
|
612
|
+
|
|
613
|
+
// simulate an external source (RPC/subgraph/DB) that stores `r` in
|
|
614
|
+
// minimal (non-zero-padded) form, as the `Hex.Hex` type permits
|
|
615
|
+
const minimalR = `0x${signature.r.slice(4)}` as const
|
|
616
|
+
const recoveredBytes = Signature.toRecoveredBytes({
|
|
617
|
+
r: minimalR,
|
|
618
|
+
s: signature.s,
|
|
619
|
+
yParity: signature.yParity,
|
|
620
|
+
})
|
|
621
|
+
const roundTripped = Signature.fromRecoveredBytes(recoveredBytes)
|
|
622
|
+
const recoveredPublicKey = Secp256k1.recoverPublicKey({
|
|
623
|
+
payload,
|
|
624
|
+
signature: roundTripped,
|
|
625
|
+
})
|
|
626
|
+
expect(recoveredPublicKey.x).toBe(expectedPublicKey.x)
|
|
627
|
+
expect(recoveredPublicKey.y).toBe(expectedPublicKey.y)
|
|
628
|
+
})
|
|
629
|
+
})
|
|
630
|
+
|
|
631
|
+
describe('fromCompactBytes', () => {
|
|
632
|
+
test('default', () => {
|
|
633
|
+
const signature = Signature.fromCompactBytes(
|
|
634
|
+
Bytes.fromHex(
|
|
635
|
+
'0x6e100a352ec6ad1b70802290e18aeed190704973570f3b8ed42cb9808e2ea6bf4a90a229a244495b41890987806fcbd2d5d23fc0dbe5f5256c2613c039d76db8',
|
|
636
|
+
),
|
|
637
|
+
)
|
|
638
|
+
expect(signature).toStrictEqual({
|
|
639
|
+
r: '0x6e100a352ec6ad1b70802290e18aeed190704973570f3b8ed42cb9808e2ea6bf',
|
|
640
|
+
s: '0x4a90a229a244495b41890987806fcbd2d5d23fc0dbe5f5256c2613c039d76db8',
|
|
641
|
+
})
|
|
642
|
+
})
|
|
643
|
+
|
|
644
|
+
test('behavior: throws on a byte length other than 64', () => {
|
|
645
|
+
expect(() => Signature.fromCompactBytes(new Uint8Array(65)))
|
|
646
|
+
.toThrowErrorMatchingInlineSnapshot(`
|
|
647
|
+
[Signature.InvalidSerializedSizeError: Value \`0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\` is an invalid signature size.
|
|
648
|
+
|
|
649
|
+
Expected: 64 bytes.
|
|
650
|
+
Received 65 bytes.]
|
|
651
|
+
`)
|
|
652
|
+
})
|
|
653
|
+
})
|
|
654
|
+
|
|
655
|
+
describe('toRecoveredBytes', () => {
|
|
656
|
+
test('default', () => {
|
|
657
|
+
const bytes = Signature.toRecoveredBytes({
|
|
658
|
+
r: '0x6e100a352ec6ad1b70802290e18aeed190704973570f3b8ed42cb9808e2ea6bf',
|
|
659
|
+
s: '0x4a90a229a244495b41890987806fcbd2d5d23fc0dbe5f5256c2613c039d76db8',
|
|
660
|
+
yParity: 1,
|
|
661
|
+
})
|
|
662
|
+
expect(bytes.length).toBe(65)
|
|
663
|
+
expect(bytes[0]).toBe(1)
|
|
664
|
+
expect(Hex.fromBytes(bytes.subarray(1))).toBe(
|
|
665
|
+
'0x6e100a352ec6ad1b70802290e18aeed190704973570f3b8ed42cb9808e2ea6bf4a90a229a244495b41890987806fcbd2d5d23fc0dbe5f5256c2613c039d76db8',
|
|
666
|
+
)
|
|
667
|
+
})
|
|
668
|
+
|
|
669
|
+
test('behavior: r/s shorter than 32 bytes are left-padded, not right-padded', () => {
|
|
670
|
+
const bytes = Signature.toRecoveredBytes({
|
|
671
|
+
r: '0x01',
|
|
672
|
+
s: '0x02',
|
|
673
|
+
yParity: 0,
|
|
674
|
+
})
|
|
675
|
+
expect(Hex.fromBytes(bytes.subarray(1, 33))).toBe(
|
|
676
|
+
'0x0000000000000000000000000000000000000000000000000000000000000001',
|
|
677
|
+
)
|
|
678
|
+
expect(Hex.fromBytes(bytes.subarray(33, 65))).toBe(
|
|
679
|
+
'0x0000000000000000000000000000000000000000000000000000000000000002',
|
|
680
|
+
)
|
|
681
|
+
})
|
|
682
|
+
|
|
683
|
+
test('behavior: throws before coercing an out-of-range yParity', () => {
|
|
684
|
+
expect(() =>
|
|
685
|
+
Signature.toRecoveredBytes({
|
|
686
|
+
r: '0x01',
|
|
687
|
+
s: '0x02',
|
|
688
|
+
yParity: 256,
|
|
689
|
+
}),
|
|
690
|
+
).toThrowErrorMatchingInlineSnapshot(
|
|
691
|
+
`[Signature.InvalidYParityError: Value \`256\` is an invalid y-parity value. Y-parity must be 0 or 1.]`,
|
|
692
|
+
)
|
|
693
|
+
})
|
|
694
|
+
})
|
|
695
|
+
|
|
696
|
+
describe('fromRecoveredBytes', () => {
|
|
697
|
+
test('default', () => {
|
|
698
|
+
const bytes = new Uint8Array(65)
|
|
699
|
+
bytes[0] = 1
|
|
700
|
+
bytes.set(
|
|
701
|
+
Bytes.fromHex(
|
|
702
|
+
'0x6e100a352ec6ad1b70802290e18aeed190704973570f3b8ed42cb9808e2ea6bf',
|
|
703
|
+
),
|
|
704
|
+
1,
|
|
705
|
+
)
|
|
706
|
+
bytes.set(
|
|
707
|
+
Bytes.fromHex(
|
|
708
|
+
'0x4a90a229a244495b41890987806fcbd2d5d23fc0dbe5f5256c2613c039d76db8',
|
|
709
|
+
),
|
|
710
|
+
33,
|
|
711
|
+
)
|
|
712
|
+
const signature = Signature.fromRecoveredBytes(bytes)
|
|
713
|
+
expect(signature).toStrictEqual({
|
|
714
|
+
r: '0x6e100a352ec6ad1b70802290e18aeed190704973570f3b8ed42cb9808e2ea6bf',
|
|
715
|
+
s: '0x4a90a229a244495b41890987806fcbd2d5d23fc0dbe5f5256c2613c039d76db8',
|
|
716
|
+
yParity: 1,
|
|
717
|
+
})
|
|
718
|
+
})
|
|
719
|
+
|
|
720
|
+
test('behavior: throws on a byte length other than 65', () => {
|
|
721
|
+
expect(() => Signature.fromRecoveredBytes(new Uint8Array(64)))
|
|
722
|
+
.toThrowErrorMatchingInlineSnapshot(`
|
|
723
|
+
[Signature.InvalidSerializedSizeError: Value \`0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\` is an invalid signature size.
|
|
724
|
+
|
|
725
|
+
Expected: 65 bytes.
|
|
726
|
+
Received 64 bytes.]
|
|
727
|
+
`)
|
|
728
|
+
})
|
|
729
|
+
|
|
730
|
+
test('behavior: throws on an out-of-range yParity byte', () => {
|
|
731
|
+
const bytes = new Uint8Array(65)
|
|
732
|
+
bytes[0] = 7
|
|
733
|
+
expect(() =>
|
|
734
|
+
Signature.fromRecoveredBytes(bytes),
|
|
735
|
+
).toThrowErrorMatchingInlineSnapshot(
|
|
736
|
+
`[Signature.InvalidYParityError: Value \`7\` is an invalid y-parity value. Y-parity must be 0 or 1.]`,
|
|
737
|
+
)
|
|
738
|
+
})
|
|
739
|
+
})
|
|
740
|
+
|
|
575
741
|
describe('toDerHex', () => {
|
|
576
742
|
test('default', () => {
|
|
577
743
|
const signature = Signature.from({
|
|
@@ -324,6 +324,53 @@ describe('createMessage', () => {
|
|
|
324
324
|
`)
|
|
325
325
|
})
|
|
326
326
|
|
|
327
|
+
test('behavior: uri with no path (authority only)', () => {
|
|
328
|
+
vi.useFakeTimers()
|
|
329
|
+
vi.setSystemTime(new Date(Date.UTC(2023, 1, 1)))
|
|
330
|
+
|
|
331
|
+
expect(Siwe.createMessage({ ...message, uri: 'https://example.com' }))
|
|
332
|
+
.toMatchInlineSnapshot(`
|
|
333
|
+
"example.com wants you to sign in with your Ethereum account:
|
|
334
|
+
0xA0Cf798816D4b9b9866b5330EEa46a18382f251e
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
URI: https://example.com
|
|
338
|
+
Version: 1
|
|
339
|
+
Chain ID: 1
|
|
340
|
+
Nonce: foobarbaz
|
|
341
|
+
Issued At: 2023-02-01T00:00:00.000Z"
|
|
342
|
+
`)
|
|
343
|
+
|
|
344
|
+
vi.useRealTimers()
|
|
345
|
+
})
|
|
346
|
+
|
|
347
|
+
test('behavior: resources entry with no path (authority only)', () => {
|
|
348
|
+
vi.useFakeTimers()
|
|
349
|
+
vi.setSystemTime(new Date(Date.UTC(2023, 1, 1)))
|
|
350
|
+
|
|
351
|
+
expect(
|
|
352
|
+
Siwe.createMessage({
|
|
353
|
+
...message,
|
|
354
|
+
resources: ['https://example.com', 'https://example.com/foo'],
|
|
355
|
+
}),
|
|
356
|
+
).toMatchInlineSnapshot(`
|
|
357
|
+
"example.com wants you to sign in with your Ethereum account:
|
|
358
|
+
0xA0Cf798816D4b9b9866b5330EEa46a18382f251e
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
URI: https://example.com/path
|
|
362
|
+
Version: 1
|
|
363
|
+
Chain ID: 1
|
|
364
|
+
Nonce: foobarbaz
|
|
365
|
+
Issued At: 2023-02-01T00:00:00.000Z
|
|
366
|
+
Resources:
|
|
367
|
+
- https://example.com
|
|
368
|
+
- https://example.com/foo"
|
|
369
|
+
`)
|
|
370
|
+
|
|
371
|
+
vi.useRealTimers()
|
|
372
|
+
})
|
|
373
|
+
|
|
327
374
|
test('behavior: invalid version', () => {
|
|
328
375
|
expect(() =>
|
|
329
376
|
// @ts-expect-error
|
|
@@ -373,7 +420,7 @@ describe('createMessage', () => {
|
|
|
373
420
|
- Every resource must be a RFC 3986 URI.
|
|
374
421
|
- See https://www.rfc-editor.org/rfc/rfc3986
|
|
375
422
|
|
|
376
|
-
Provided value:
|
|
423
|
+
Provided value: foo]
|
|
377
424
|
`)
|
|
378
425
|
})
|
|
379
426
|
|
|
@@ -426,6 +473,58 @@ describe('isUri', () => {
|
|
|
426
473
|
)
|
|
427
474
|
})
|
|
428
475
|
|
|
476
|
+
test('behavior: authority with empty path (bare origin)', () => {
|
|
477
|
+
expect(Siwe.isUri('https://example.com')).toMatchInlineSnapshot(
|
|
478
|
+
`"https://example.com"`,
|
|
479
|
+
)
|
|
480
|
+
})
|
|
481
|
+
|
|
482
|
+
test('behavior: authority with empty path and port', () => {
|
|
483
|
+
expect(Siwe.isUri('https://example.com:8080')).toMatchInlineSnapshot(
|
|
484
|
+
`"https://example.com:8080"`,
|
|
485
|
+
)
|
|
486
|
+
})
|
|
487
|
+
|
|
488
|
+
test('behavior: authority with empty path and query', () => {
|
|
489
|
+
expect(Siwe.isUri('https://example.com?a=1')).toMatchInlineSnapshot(
|
|
490
|
+
`"https://example.com?a=1"`,
|
|
491
|
+
)
|
|
492
|
+
})
|
|
493
|
+
|
|
494
|
+
test('behavior: authority with empty path and fragment', () => {
|
|
495
|
+
expect(Siwe.isUri('https://example.com#top')).toMatchInlineSnapshot(
|
|
496
|
+
`"https://example.com#top"`,
|
|
497
|
+
)
|
|
498
|
+
})
|
|
499
|
+
|
|
500
|
+
test('behavior: authority with empty path (non-http scheme)', () => {
|
|
501
|
+
expect(Siwe.isUri('ipfs://bafybeiabc')).toMatchInlineSnapshot(
|
|
502
|
+
`"ipfs://bafybeiabc"`,
|
|
503
|
+
)
|
|
504
|
+
})
|
|
505
|
+
|
|
506
|
+
test('behavior: authority variants with empty path', () => {
|
|
507
|
+
expect([
|
|
508
|
+
Siwe.isUri('https://[2001:db8::1]'),
|
|
509
|
+
Siwe.isUri('https://user:pass@example.com:8080'),
|
|
510
|
+
Siwe.isUri('foo://[v1.fe]'),
|
|
511
|
+
]).toMatchInlineSnapshot(`
|
|
512
|
+
[
|
|
513
|
+
"https://[2001:db8::1]",
|
|
514
|
+
"https://user:pass@example.com:8080",
|
|
515
|
+
"foo://[v1.fe]",
|
|
516
|
+
]
|
|
517
|
+
`)
|
|
518
|
+
})
|
|
519
|
+
|
|
520
|
+
test.each([
|
|
521
|
+
'https://example.com:bad',
|
|
522
|
+
'https://[:::]',
|
|
523
|
+
'https://user@@example.com',
|
|
524
|
+
])('behavior: invalid authority with empty path `%s`', (uri) => {
|
|
525
|
+
expect(Siwe.isUri(uri)).toMatchInlineSnapshot(`false`)
|
|
526
|
+
})
|
|
527
|
+
|
|
429
528
|
test('behavior: check for illegal characters', () => {
|
|
430
529
|
expect(Siwe.isUri('^')).toBeFalsy()
|
|
431
530
|
})
|
|
@@ -3,6 +3,9 @@ import {
|
|
|
3
3
|
Secp256k1,
|
|
4
4
|
Transaction,
|
|
5
5
|
TxEnvelopeEip1559,
|
|
6
|
+
Frame,
|
|
7
|
+
FrameSignature,
|
|
8
|
+
TxEnvelopeEip8141,
|
|
6
9
|
TxEnvelopeLegacy,
|
|
7
10
|
} from 'ox'
|
|
8
11
|
import { describe, expect, test } from 'vp/test'
|
|
@@ -2046,3 +2049,33 @@ test('exports', () => {
|
|
|
2046
2049
|
]
|
|
2047
2050
|
`)
|
|
2048
2051
|
})
|
|
2052
|
+
|
|
2053
|
+
describe('frame transaction RPC', () => {
|
|
2054
|
+
test('preserves pending metadata and large chain IDs without outer signatures', () => {
|
|
2055
|
+
const envelope = TxEnvelopeEip8141.from({
|
|
2056
|
+
chainId: 9007199254740993n,
|
|
2057
|
+
frames: [Frame.from({})],
|
|
2058
|
+
sender: '0x1111111111111111111111111111111111111111',
|
|
2059
|
+
signatures: [FrameSignature.from({ scheme: 'secp256k1' })],
|
|
2060
|
+
})
|
|
2061
|
+
const rpc = {
|
|
2062
|
+
...TxEnvelopeEip8141.toRpc(envelope),
|
|
2063
|
+
blockHash: null,
|
|
2064
|
+
blockNumber: null,
|
|
2065
|
+
blockTimestamp: null,
|
|
2066
|
+
gas: '0x0',
|
|
2067
|
+
hash: '0x00',
|
|
2068
|
+
input: '0x',
|
|
2069
|
+
to: null,
|
|
2070
|
+
transactionIndex: null,
|
|
2071
|
+
value: '0x0',
|
|
2072
|
+
} satisfies Transaction.Eip8141Rpc<true>
|
|
2073
|
+
const transaction = Transaction.fromRpc(rpc, { pending: true })!
|
|
2074
|
+
expect(transaction.chainId).toBe(9007199254740993n)
|
|
2075
|
+
expect(transaction.blockNumber).toBeNull()
|
|
2076
|
+
expect(transaction.transactionIndex).toBeNull()
|
|
2077
|
+
expect(transaction).not.toHaveProperty('r')
|
|
2078
|
+
expect(transaction).not.toHaveProperty('s')
|
|
2079
|
+
expect(Transaction.toRpc(transaction, { pending: true })).toEqual(rpc)
|
|
2080
|
+
})
|
|
2081
|
+
})
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
type TxEnvelopeEip2930,
|
|
5
5
|
type TxEnvelopeEip4844,
|
|
6
6
|
type TxEnvelopeEip7702,
|
|
7
|
+
type TxEnvelopeEip8141,
|
|
7
8
|
type TxEnvelopeLegacy,
|
|
8
9
|
} from 'ox'
|
|
9
10
|
import { describe, expectTypeOf, test } from 'vp/test'
|
|
@@ -180,3 +181,76 @@ describe('toRpc', () => {
|
|
|
180
181
|
expectTypeOf(rpc).toEqualTypeOf<TxEnvelopeEip1559.Rpc>()
|
|
181
182
|
})
|
|
182
183
|
})
|
|
184
|
+
|
|
185
|
+
describe('eip8141', () => {
|
|
186
|
+
test('preserves constructor literals', () => {
|
|
187
|
+
const envelope = TransactionEnvelope.from({
|
|
188
|
+
chainId: 1n,
|
|
189
|
+
frames: [],
|
|
190
|
+
sender: '0x1111111111111111111111111111111111111111',
|
|
191
|
+
})
|
|
192
|
+
expectTypeOf(envelope).toEqualTypeOf<{
|
|
193
|
+
readonly chainId: 1n
|
|
194
|
+
readonly frames: readonly []
|
|
195
|
+
readonly sender: '0x1111111111111111111111111111111111111111'
|
|
196
|
+
readonly type: 'eip8141'
|
|
197
|
+
}>()
|
|
198
|
+
expectTypeOf(
|
|
199
|
+
TransactionEnvelope.serialize(envelope),
|
|
200
|
+
).toEqualTypeOf<TxEnvelopeEip8141.Serialized>()
|
|
201
|
+
expectTypeOf(
|
|
202
|
+
TransactionEnvelope.deserialize('0x06c0'),
|
|
203
|
+
).toEqualTypeOf<TxEnvelopeEip8141.TxEnvelopeEip8141>()
|
|
204
|
+
expectTypeOf(
|
|
205
|
+
TransactionEnvelope.from('0x06c0'),
|
|
206
|
+
).toEqualTypeOf<TxEnvelopeEip8141.TxEnvelopeEip8141>()
|
|
207
|
+
expectTypeOf(
|
|
208
|
+
TransactionEnvelope.getSerializedType('0x06c0'),
|
|
209
|
+
).toEqualTypeOf<'eip8141'>()
|
|
210
|
+
expectTypeOf(envelope).toMatchTypeOf<TransactionEnvelope.TxEnvelope<true>>()
|
|
211
|
+
expectTypeOf(
|
|
212
|
+
TransactionEnvelope.toRpc(envelope),
|
|
213
|
+
).toEqualTypeOf<TxEnvelopeEip8141.Rpc>()
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
test('frames take precedence over blob and fee fields', () => {
|
|
217
|
+
expectTypeOf(
|
|
218
|
+
TransactionEnvelope.getType({
|
|
219
|
+
blobVersionedHashes: [],
|
|
220
|
+
frames: [],
|
|
221
|
+
maxFeePerGas: 1n,
|
|
222
|
+
}),
|
|
223
|
+
).toEqualTypeOf<'eip8141'>()
|
|
224
|
+
expectTypeOf(
|
|
225
|
+
TransactionEnvelope.getType({ frames: undefined, maxFeePerGas: 1n }),
|
|
226
|
+
).toEqualTypeOf<'eip1559'>()
|
|
227
|
+
expectTypeOf(
|
|
228
|
+
TransactionEnvelope.getType({ frames: [], type: 'eip1559' }),
|
|
229
|
+
).toEqualTypeOf<'eip1559'>()
|
|
230
|
+
})
|
|
231
|
+
})
|
|
232
|
+
|
|
233
|
+
test('toRpc accepts implicit frame envelopes', () => {
|
|
234
|
+
const envelope = {
|
|
235
|
+
chainId: 1,
|
|
236
|
+
frames: [{}],
|
|
237
|
+
sender: '0x1111111111111111111111111111111111111111',
|
|
238
|
+
} as const
|
|
239
|
+
expectTypeOf(
|
|
240
|
+
TransactionEnvelope.toRpc(envelope),
|
|
241
|
+
).toEqualTypeOf<TxEnvelopeEip8141.Rpc>()
|
|
242
|
+
})
|
|
243
|
+
|
|
244
|
+
test('request conversions accept frames and undefined', () => {
|
|
245
|
+
TransactionEnvelope.toRpc({ chainId: 1, frames: undefined, maxFeePerGas: 1n })
|
|
246
|
+
TransactionEnvelope.toTransactionRequest({
|
|
247
|
+
chainId: 1,
|
|
248
|
+
frames: undefined,
|
|
249
|
+
maxFeePerGas: 1n,
|
|
250
|
+
})
|
|
251
|
+
TransactionEnvelope.toTransactionRequest({
|
|
252
|
+
chainId: 1,
|
|
253
|
+
frames: [{}],
|
|
254
|
+
sender: '0x1111111111111111111111111111111111111111',
|
|
255
|
+
})
|
|
256
|
+
})
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
|
+
Frame,
|
|
3
|
+
FrameSignature,
|
|
2
4
|
TransactionEnvelope,
|
|
3
5
|
TxEnvelopeEip1559,
|
|
4
6
|
TxEnvelopeEip2930,
|
|
5
7
|
TxEnvelopeEip4844,
|
|
6
8
|
TxEnvelopeEip7702,
|
|
9
|
+
TxEnvelopeEip8141,
|
|
7
10
|
TxEnvelopeLegacy,
|
|
8
11
|
} from 'ox'
|
|
9
12
|
import { describe, expect, test } from 'vp/test'
|
|
@@ -62,6 +65,14 @@ const eip7702 = TxEnvelopeEip7702.from({
|
|
|
62
65
|
value: 1n,
|
|
63
66
|
})
|
|
64
67
|
|
|
68
|
+
const eip8141 = TxEnvelopeEip8141.from({
|
|
69
|
+
chainId: 1,
|
|
70
|
+
frames: [Frame.from({})],
|
|
71
|
+
sender: '0x1111111111111111111111111111111111111111',
|
|
72
|
+
})
|
|
73
|
+
const serialized8141 =
|
|
74
|
+
'0x06e70180941111111111111111111111111111111111111111c9c8808080c280808080c0c3808080c0'
|
|
75
|
+
|
|
65
76
|
test('exports', () => {
|
|
66
77
|
expect(Object.keys(TransactionEnvelope)).toMatchInlineSnapshot(`
|
|
67
78
|
[
|
|
@@ -88,6 +99,25 @@ test('exports', () => {
|
|
|
88
99
|
})
|
|
89
100
|
|
|
90
101
|
describe('getType', () => {
|
|
102
|
+
test('frame fields take precedence over blobs and fees', () => {
|
|
103
|
+
expect(
|
|
104
|
+
TransactionEnvelope.getType({
|
|
105
|
+
blobVersionedHashes: [],
|
|
106
|
+
frames: [],
|
|
107
|
+
maxFeePerGas: 1n,
|
|
108
|
+
}),
|
|
109
|
+
).toBe('eip8141')
|
|
110
|
+
expect(
|
|
111
|
+
TransactionEnvelope.getType({ frames: undefined, maxFeePerGas: 1n }),
|
|
112
|
+
).toBe('eip1559')
|
|
113
|
+
expect(TransactionEnvelope.getType({ frames: [], type: 'eip1559' })).toBe(
|
|
114
|
+
'eip1559',
|
|
115
|
+
)
|
|
116
|
+
expect(() => TransactionEnvelope.getType({ type: '0x6' })).toThrow(
|
|
117
|
+
TransactionEnvelope.InvalidTypeError,
|
|
118
|
+
)
|
|
119
|
+
})
|
|
120
|
+
|
|
91
121
|
test('behavior: routes explicit transaction types', () => {
|
|
92
122
|
expect(TransactionEnvelope.getType(legacy)).toBe('legacy')
|
|
93
123
|
expect(TransactionEnvelope.getType(eip2930)).toBe('eip2930')
|
|
@@ -156,6 +186,12 @@ describe('getType', () => {
|
|
|
156
186
|
})
|
|
157
187
|
|
|
158
188
|
describe('getSerializedType', () => {
|
|
189
|
+
test('eip8141', () => {
|
|
190
|
+
expect(TransactionEnvelope.getSerializedType(serialized8141)).toBe(
|
|
191
|
+
'eip8141',
|
|
192
|
+
)
|
|
193
|
+
})
|
|
194
|
+
|
|
159
195
|
test('behavior: routes serialized transaction types', () => {
|
|
160
196
|
expect(
|
|
161
197
|
TransactionEnvelope.getSerializedType(TxEnvelopeLegacy.serialize(legacy)),
|
|
@@ -202,6 +238,12 @@ describe('getSerializedType', () => {
|
|
|
202
238
|
})
|
|
203
239
|
|
|
204
240
|
describe('deserialize', () => {
|
|
241
|
+
test('eip8141', () => {
|
|
242
|
+
expect(TransactionEnvelope.deserialize(serialized8141)).toEqual(
|
|
243
|
+
TxEnvelopeEip8141.deserialize(serialized8141),
|
|
244
|
+
)
|
|
245
|
+
})
|
|
246
|
+
|
|
205
247
|
test('behavior: routes to the matching concrete deserializer', () => {
|
|
206
248
|
const serialized = TxEnvelopeEip1559.serialize(eip1559)
|
|
207
249
|
|
|
@@ -212,6 +254,14 @@ describe('deserialize', () => {
|
|
|
212
254
|
})
|
|
213
255
|
|
|
214
256
|
describe('from', () => {
|
|
257
|
+
test('eip8141', () => {
|
|
258
|
+
const { type: _, ...input } = eip8141
|
|
259
|
+
expect(TransactionEnvelope.from(input)).toEqual(eip8141)
|
|
260
|
+
expect(TransactionEnvelope.from(serialized8141)).toEqual(
|
|
261
|
+
TxEnvelopeEip8141.deserialize(serialized8141),
|
|
262
|
+
)
|
|
263
|
+
})
|
|
264
|
+
|
|
215
265
|
test('behavior: routes objects to the matching concrete converter', () => {
|
|
216
266
|
expect(TransactionEnvelope.from({ maxFeePerGas: 10n, chainId: 1 })).toEqual(
|
|
217
267
|
TxEnvelopeEip1559.from({ maxFeePerGas: 10n, chainId: 1 }),
|
|
@@ -244,6 +294,26 @@ describe('from', () => {
|
|
|
244
294
|
})
|
|
245
295
|
|
|
246
296
|
describe('getSignPayload', () => {
|
|
297
|
+
test('eip8141 signature elision', () => {
|
|
298
|
+
const envelope = TxEnvelopeEip8141.from({
|
|
299
|
+
...eip8141,
|
|
300
|
+
signatures: [
|
|
301
|
+
FrameSignature.from('0xaabb'),
|
|
302
|
+
FrameSignature.from({
|
|
303
|
+
payload: `0x${'ab'.repeat(32)}`,
|
|
304
|
+
signature: '0xccdd',
|
|
305
|
+
}),
|
|
306
|
+
],
|
|
307
|
+
})
|
|
308
|
+
expect(TransactionEnvelope.getSignPayload(envelope)).toBe(
|
|
309
|
+
'0x85ec4544ddb227c5425add4b606f71ddfc0852100d14066d0061a1b092bad6d3',
|
|
310
|
+
)
|
|
311
|
+
expect(TransactionEnvelope.hash(envelope, { presign: true })).toBe(
|
|
312
|
+
TransactionEnvelope.getSignPayload(envelope),
|
|
313
|
+
)
|
|
314
|
+
expect(envelope.signatures[0].signature).toBe('0xaabb')
|
|
315
|
+
})
|
|
316
|
+
|
|
247
317
|
test('behavior: routes to the matching concrete payload helper', () => {
|
|
248
318
|
expect(TransactionEnvelope.getSignPayload(eip1559)).toBe(
|
|
249
319
|
TxEnvelopeEip1559.getSignPayload(eip1559),
|
|
@@ -252,6 +322,12 @@ describe('getSignPayload', () => {
|
|
|
252
322
|
})
|
|
253
323
|
|
|
254
324
|
describe('hash', () => {
|
|
325
|
+
test('eip8141 without outer signature fields', () => {
|
|
326
|
+
expect(TransactionEnvelope.hash(eip8141)).toBe(
|
|
327
|
+
'0xa795b6de44696d46c096aaa3d6401d6eaa21b9b639408c82be7e9e60358e4387',
|
|
328
|
+
)
|
|
329
|
+
})
|
|
330
|
+
|
|
255
331
|
test('behavior: routes to the matching concrete hash helper', () => {
|
|
256
332
|
expect(TransactionEnvelope.hash(eip1559, { presign: true })).toBe(
|
|
257
333
|
TxEnvelopeEip1559.hash(eip1559, { presign: true }),
|
|
@@ -260,6 +336,10 @@ describe('hash', () => {
|
|
|
260
336
|
})
|
|
261
337
|
|
|
262
338
|
describe('serialize', () => {
|
|
339
|
+
test('eip8141', () => {
|
|
340
|
+
expect(TransactionEnvelope.serialize(eip8141)).toBe(serialized8141)
|
|
341
|
+
})
|
|
342
|
+
|
|
263
343
|
test('behavior: routes to the matching concrete serializer', () => {
|
|
264
344
|
expect(TransactionEnvelope.serialize(eip1559)).toBe(
|
|
265
345
|
TxEnvelopeEip1559.serialize(eip1559),
|
|
@@ -284,6 +364,12 @@ describe('serialize', () => {
|
|
|
284
364
|
})
|
|
285
365
|
|
|
286
366
|
describe('toRpc', () => {
|
|
367
|
+
test('converts frame envelopes', () => {
|
|
368
|
+
expect(TransactionEnvelope.toRpc(eip8141)).toEqual(
|
|
369
|
+
TxEnvelopeEip8141.toRpc(eip8141),
|
|
370
|
+
)
|
|
371
|
+
})
|
|
372
|
+
|
|
287
373
|
test('behavior: routes to the matching concrete RPC converter', () => {
|
|
288
374
|
expect(TransactionEnvelope.toRpc(eip1559)).toEqual(
|
|
289
375
|
TxEnvelopeEip1559.toRpc(eip1559),
|
|
@@ -292,6 +378,13 @@ describe('toRpc', () => {
|
|
|
292
378
|
})
|
|
293
379
|
|
|
294
380
|
describe('assert', () => {
|
|
381
|
+
test('eip8141', () => {
|
|
382
|
+
expect(() => TransactionEnvelope.assert(eip8141)).not.toThrow()
|
|
383
|
+
expect(() =>
|
|
384
|
+
TransactionEnvelope.assert({ ...eip8141, frames: [] }),
|
|
385
|
+
).toThrow(TxEnvelopeEip8141.InvalidError)
|
|
386
|
+
})
|
|
387
|
+
|
|
295
388
|
test('behavior: routes to the matching concrete assertion', () => {
|
|
296
389
|
expect(() =>
|
|
297
390
|
TransactionEnvelope.assert({
|
|
@@ -306,6 +399,11 @@ describe('assert', () => {
|
|
|
306
399
|
})
|
|
307
400
|
|
|
308
401
|
describe('validate', () => {
|
|
402
|
+
test('eip8141', () => {
|
|
403
|
+
expect(TransactionEnvelope.validate(eip8141)).toBe(true)
|
|
404
|
+
expect(TransactionEnvelope.validate({ ...eip8141, frames: [] })).toBe(false)
|
|
405
|
+
})
|
|
406
|
+
|
|
309
407
|
test('behavior: returns validation result for routed envelope', () => {
|
|
310
408
|
expect(TransactionEnvelope.validate(eip1559)).toBe(true)
|
|
311
409
|
expect(
|
|
@@ -333,6 +431,15 @@ describe('getType', () => {
|
|
|
333
431
|
})
|
|
334
432
|
|
|
335
433
|
describe('toTransactionRequest', () => {
|
|
434
|
+
test('maps frame sender to request from', () => {
|
|
435
|
+
expect(TransactionEnvelope.toTransactionRequest(eip8141)).toEqual({
|
|
436
|
+
chainId: 1,
|
|
437
|
+
frames: [{}],
|
|
438
|
+
from: '0x1111111111111111111111111111111111111111',
|
|
439
|
+
type: 'eip8141',
|
|
440
|
+
})
|
|
441
|
+
})
|
|
442
|
+
|
|
336
443
|
test('behavior: eip1559', () => {
|
|
337
444
|
const request = TransactionEnvelope.toTransactionRequest(eip1559)
|
|
338
445
|
expect(request).toMatchInlineSnapshot(`
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { TransactionReceipt } from 'ox'
|
|
2
|
+
import { z } from 'ox/zod'
|
|
2
3
|
import { describe, expect, test } from 'vp/test'
|
|
3
4
|
import { anvilMainnet } from '../../../test/prool.js'
|
|
4
5
|
|
|
@@ -457,3 +458,61 @@ test('exports', () => {
|
|
|
457
458
|
]
|
|
458
459
|
`)
|
|
459
460
|
})
|
|
461
|
+
|
|
462
|
+
describe('frame receipts', () => {
|
|
463
|
+
test('preserves payer, statuses, logs, and large gas totals', () => {
|
|
464
|
+
const rpc = {
|
|
465
|
+
blockHash: '0x00',
|
|
466
|
+
blockNumber: '0x1',
|
|
467
|
+
cumulativeGasUsed: '0x20000000000001',
|
|
468
|
+
effectiveGasPrice: '0x1',
|
|
469
|
+
frameReceipts: [
|
|
470
|
+
{
|
|
471
|
+
executionGasUsed: '0x20000000000001',
|
|
472
|
+
logs: [
|
|
473
|
+
{
|
|
474
|
+
address: '0x1111111111111111111111111111111111111111',
|
|
475
|
+
data: '0xab',
|
|
476
|
+
topics: ['0x01'],
|
|
477
|
+
},
|
|
478
|
+
],
|
|
479
|
+
stateGasUsed: '0x2',
|
|
480
|
+
status: 1,
|
|
481
|
+
},
|
|
482
|
+
{ executionGasUsed: '0x3', logs: [], stateGasUsed: '0x0', status: 0 },
|
|
483
|
+
{ executionGasUsed: '0x0', logs: [], stateGasUsed: '0x0', status: 2 },
|
|
484
|
+
],
|
|
485
|
+
from: '0x1111111111111111111111111111111111111111',
|
|
486
|
+
gasUsed: '0x20000000000001',
|
|
487
|
+
logs: [],
|
|
488
|
+
logsBloom: '0x00',
|
|
489
|
+
payer: '0x2222222222222222222222222222222222222222',
|
|
490
|
+
status: '0x0',
|
|
491
|
+
to: null,
|
|
492
|
+
transactionHash: '0x00',
|
|
493
|
+
transactionIndex: '0x0',
|
|
494
|
+
type: '0x6',
|
|
495
|
+
} satisfies TransactionReceipt.Rpc
|
|
496
|
+
const receipt = TransactionReceipt.fromRpc(rpc)
|
|
497
|
+
expect(receipt.type).toBe('eip8141')
|
|
498
|
+
expect(receipt.payer).toBe(rpc.payer)
|
|
499
|
+
expect(receipt.frameReceipts).toEqual([
|
|
500
|
+
{
|
|
501
|
+
gasUsed: 9007199254740993n,
|
|
502
|
+
logs: rpc.frameReceipts[0]!.logs,
|
|
503
|
+
stateGasUsed: 2n,
|
|
504
|
+
status: 'success',
|
|
505
|
+
},
|
|
506
|
+
{ gasUsed: 3n, logs: [], stateGasUsed: 0n, status: 'reverted' },
|
|
507
|
+
{ gasUsed: 0n, logs: [], stateGasUsed: 0n, status: 'skipped' },
|
|
508
|
+
])
|
|
509
|
+
expect(TransactionReceipt.toRpc(receipt)).toMatchObject(rpc)
|
|
510
|
+
expect(
|
|
511
|
+
z.decode(z.TransactionReceipt.TransactionReceipt, rpc).frameReceipts,
|
|
512
|
+
).toEqual(receipt.frameReceipts)
|
|
513
|
+
expect(
|
|
514
|
+
z.encode(z.TransactionReceipt.TransactionReceipt, receipt).frameReceipts,
|
|
515
|
+
).toEqual(rpc.frameReceipts)
|
|
516
|
+
expect(rpc.frameReceipts[0]!.executionGasUsed).toBe('0x20000000000001')
|
|
517
|
+
})
|
|
518
|
+
})
|