ox 0.14.25 → 0.14.26

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/tempo/e2e.test.ts CHANGED
@@ -2662,4 +2662,334 @@ describe('behavior: keyAuthorization', () => {
2662
2662
  ).rejects.toThrow()
2663
2663
  },
2664
2664
  )
2665
+
2666
+ // TODO: remove skipIf when devnet/testnet have T5 (TIP-1053).
2667
+ test.skipIf(nodeEnv !== 'localnet')(
2668
+ 'behavior: TIP-1053 witness round-trips through registration',
2669
+ async () => {
2670
+ const accessPrivateKey = Secp256k1.randomPrivateKey()
2671
+ const accessAddress = Address.fromPublicKey(
2672
+ Secp256k1.getPublicKey({ privateKey: accessPrivateKey }),
2673
+ )
2674
+
2675
+ // Application-defined challenge digest, bound to the authorization.
2676
+ const witness = Hex.random(32)
2677
+
2678
+ const keyAuth = KeyAuthorization.from({
2679
+ address: accessAddress,
2680
+ chainId: BigInt(chainId),
2681
+ type: 'secp256k1',
2682
+ witness,
2683
+ })
2684
+
2685
+ const keyAuth_signed = KeyAuthorization.from(keyAuth, {
2686
+ signature: SignatureEnvelope.from(
2687
+ Secp256k1.sign({
2688
+ payload: KeyAuthorization.getSignPayload(keyAuth),
2689
+ privateKey: root.privateKey,
2690
+ }),
2691
+ ),
2692
+ })
2693
+
2694
+ const nonce = await getTransactionCount(client, {
2695
+ address: root.address,
2696
+ blockTag: 'pending',
2697
+ })
2698
+
2699
+ const transaction = TxEnvelopeTempo.from({
2700
+ calls: [{ to: '0x0000000000000000000000000000000000000000' }],
2701
+ chainId,
2702
+ feeToken: '0x20c0000000000000000000000000000000000001',
2703
+ keyAuthorization: keyAuth_signed,
2704
+ nonce: BigInt(nonce),
2705
+ gas: 1_000_000n,
2706
+ maxFeePerGas: Value.fromGwei('20'),
2707
+ maxPriorityFeePerGas: Value.fromGwei('10'),
2708
+ })
2709
+
2710
+ const signature = Secp256k1.sign({
2711
+ payload: TxEnvelopeTempo.getSignPayload(transaction, {
2712
+ from: root.address,
2713
+ }),
2714
+ privateKey: accessPrivateKey,
2715
+ })
2716
+
2717
+ const serialized_signed = TxEnvelopeTempo.serialize(transaction, {
2718
+ signature: SignatureEnvelope.from({
2719
+ userAddress: root.address,
2720
+ inner: SignatureEnvelope.from(signature),
2721
+ type: 'keychain',
2722
+ }),
2723
+ })
2724
+
2725
+ const receipt = (await client
2726
+ .request({
2727
+ method: 'eth_sendRawTransactionSync',
2728
+ params: [serialized_signed],
2729
+ })
2730
+ .then((tx) => TransactionReceipt.fromRpc(tx as any)))!
2731
+ expect(receipt.status).toBe('success')
2732
+
2733
+ const response = await client
2734
+ .request({
2735
+ method: 'eth_getTransactionByHash',
2736
+ params: [receipt.transactionHash],
2737
+ })
2738
+ .then((tx) => Transaction.fromRpc(tx as any))
2739
+ if (!response) throw new Error()
2740
+
2741
+ // The witness must survive the round trip through the node.
2742
+ expect(response.keyAuthorization?.witness).toBe(witness)
2743
+
2744
+ // The signing hash of the round-tripped authorization equals the witness-bearing hash.
2745
+ expect(KeyAuthorization.hash(response.keyAuthorization!)).toBe(
2746
+ KeyAuthorization.hash(keyAuth_signed),
2747
+ )
2748
+ },
2749
+ )
2750
+
2751
+ // TODO: remove skipIf when devnet/testnet have T5
2752
+ test.skipIf(nodeEnv !== 'localnet')(
2753
+ 'behavior: TIP-1053 witness-less authorization is byte-equivalent to pre-TIP-1053',
2754
+ async () => {
2755
+ // Two authorizations with identical fields but different access keys; the witness-less
2756
+ // shape must encode without a trailing witness slot.
2757
+ const accessPrivateKey = Secp256k1.randomPrivateKey()
2758
+ const accessAddress = Address.fromPublicKey(
2759
+ Secp256k1.getPublicKey({ privateKey: accessPrivateKey }),
2760
+ )
2761
+ const keyAuth = KeyAuthorization.from({
2762
+ address: accessAddress,
2763
+ chainId: BigInt(chainId),
2764
+ type: 'secp256k1',
2765
+ })
2766
+ const [authTuple] = KeyAuthorization.toTuple(keyAuth)
2767
+ expect((authTuple as unknown as unknown[]).length).toBe(3)
2768
+
2769
+ const keyAuth_signed = KeyAuthorization.from(keyAuth, {
2770
+ signature: SignatureEnvelope.from(
2771
+ Secp256k1.sign({
2772
+ payload: KeyAuthorization.getSignPayload(keyAuth),
2773
+ privateKey: root.privateKey,
2774
+ }),
2775
+ ),
2776
+ })
2777
+
2778
+ const nonce = await getTransactionCount(client, {
2779
+ address: root.address,
2780
+ blockTag: 'pending',
2781
+ })
2782
+
2783
+ const transaction = TxEnvelopeTempo.from({
2784
+ calls: [{ to: '0x0000000000000000000000000000000000000000' }],
2785
+ chainId,
2786
+ feeToken: '0x20c0000000000000000000000000000000000001',
2787
+ keyAuthorization: keyAuth_signed,
2788
+ nonce: BigInt(nonce),
2789
+ gas: 1_000_000n,
2790
+ maxFeePerGas: Value.fromGwei('20'),
2791
+ maxPriorityFeePerGas: Value.fromGwei('10'),
2792
+ })
2793
+
2794
+ const signature = Secp256k1.sign({
2795
+ payload: TxEnvelopeTempo.getSignPayload(transaction, {
2796
+ from: root.address,
2797
+ }),
2798
+ privateKey: accessPrivateKey,
2799
+ })
2800
+
2801
+ const serialized_signed = TxEnvelopeTempo.serialize(transaction, {
2802
+ signature: SignatureEnvelope.from({
2803
+ userAddress: root.address,
2804
+ inner: SignatureEnvelope.from(signature),
2805
+ type: 'keychain',
2806
+ }),
2807
+ })
2808
+
2809
+ const receipt = (await client
2810
+ .request({
2811
+ method: 'eth_sendRawTransactionSync',
2812
+ params: [serialized_signed],
2813
+ })
2814
+ .then((tx) => TransactionReceipt.fromRpc(tx as any)))!
2815
+ expect(receipt.status).toBe('success')
2816
+
2817
+ const response = await client
2818
+ .request({
2819
+ method: 'eth_getTransactionByHash',
2820
+ params: [receipt.transactionHash],
2821
+ })
2822
+ .then((tx) => Transaction.fromRpc(tx as any))
2823
+ if (!response) throw new Error()
2824
+
2825
+ expect(response.keyAuthorization?.witness).toBeUndefined()
2826
+ },
2827
+ )
2828
+
2829
+ // TODO: remove skipIf when devnet/testnet have T6 (TIP-1049).
2830
+ test.skipIf(nodeEnv !== 'localnet')(
2831
+ 'behavior: TIP-1049 admin access key round-trips through registration',
2832
+ async () => {
2833
+ const accessPrivateKey = Secp256k1.randomPrivateKey()
2834
+ const accessAddress = Address.fromPublicKey(
2835
+ Secp256k1.getPublicKey({ privateKey: accessPrivateKey }),
2836
+ )
2837
+
2838
+ const keyAuth = KeyAuthorization.from({
2839
+ address: accessAddress,
2840
+ account: root.address,
2841
+ chainId: BigInt(chainId),
2842
+ isAdmin: true,
2843
+ type: 'secp256k1',
2844
+ })
2845
+
2846
+ const keyAuth_signed = KeyAuthorization.from(keyAuth, {
2847
+ signature: SignatureEnvelope.from(
2848
+ Secp256k1.sign({
2849
+ payload: KeyAuthorization.getSignPayload(keyAuth),
2850
+ privateKey: root.privateKey,
2851
+ }),
2852
+ ),
2853
+ })
2854
+
2855
+ const nonce = await getTransactionCount(client, {
2856
+ address: root.address,
2857
+ blockTag: 'pending',
2858
+ })
2859
+
2860
+ const transaction = TxEnvelopeTempo.from({
2861
+ calls: [{ to: '0x0000000000000000000000000000000000000000' }],
2862
+ chainId,
2863
+ feeToken: '0x20c0000000000000000000000000000000000001',
2864
+ keyAuthorization: keyAuth_signed,
2865
+ nonce: BigInt(nonce),
2866
+ gas: 1_000_000n,
2867
+ maxFeePerGas: Value.fromGwei('20'),
2868
+ maxPriorityFeePerGas: Value.fromGwei('10'),
2869
+ })
2870
+
2871
+ // The admin access key signs and authorizes itself in the same tx
2872
+ // (the canonical "auth+use" registration pattern).
2873
+ const signature = Secp256k1.sign({
2874
+ payload: TxEnvelopeTempo.getSignPayload(transaction, {
2875
+ from: root.address,
2876
+ }),
2877
+ privateKey: accessPrivateKey,
2878
+ })
2879
+
2880
+ const serialized_signed = TxEnvelopeTempo.serialize(transaction, {
2881
+ signature: SignatureEnvelope.from({
2882
+ userAddress: root.address,
2883
+ inner: SignatureEnvelope.from(signature),
2884
+ type: 'keychain',
2885
+ }),
2886
+ })
2887
+
2888
+ const receipt = (await client
2889
+ .request({
2890
+ method: 'eth_sendRawTransactionSync',
2891
+ params: [serialized_signed],
2892
+ })
2893
+ .then((tx) => TransactionReceipt.fromRpc(tx as any)))!
2894
+ expect(receipt.status).toBe('success')
2895
+
2896
+ const response = await client
2897
+ .request({
2898
+ method: 'eth_getTransactionByHash',
2899
+ params: [receipt.transactionHash],
2900
+ })
2901
+ .then((tx) => Transaction.fromRpc(tx as any))
2902
+ if (!response) throw new Error()
2903
+
2904
+ // isAdmin + account must survive the round trip through the node.
2905
+ expect(response.keyAuthorization?.isAdmin).toBe(true)
2906
+ expect(response.keyAuthorization?.account).toBe(root.address)
2907
+
2908
+ // The signing hash of the round-tripped authorization equals the
2909
+ // admin-bearing hash.
2910
+ expect(KeyAuthorization.hash(response.keyAuthorization!)).toBe(
2911
+ KeyAuthorization.hash(keyAuth_signed),
2912
+ )
2913
+ },
2914
+ )
2915
+
2916
+ // TODO: remove skipIf when devnet/testnet have T6.
2917
+ test.skipIf(nodeEnv !== 'localnet')(
2918
+ 'behavior: TIP-1049 non-admin authorization is byte-equivalent to pre-TIP-1049',
2919
+ async () => {
2920
+ const accessPrivateKey = Secp256k1.randomPrivateKey()
2921
+ const accessAddress = Address.fromPublicKey(
2922
+ Secp256k1.getPublicKey({ privateKey: accessPrivateKey }),
2923
+ )
2924
+
2925
+ // Without isAdmin or account, the encoded tuple must not carry trailing
2926
+ // TIP-1049 slots.
2927
+ const keyAuth = KeyAuthorization.from({
2928
+ address: accessAddress,
2929
+ chainId: BigInt(chainId),
2930
+ type: 'secp256k1',
2931
+ })
2932
+ const [authTuple] = KeyAuthorization.toTuple(keyAuth)
2933
+ expect((authTuple as unknown as unknown[]).length).toBe(3)
2934
+
2935
+ const keyAuth_signed = KeyAuthorization.from(keyAuth, {
2936
+ signature: SignatureEnvelope.from(
2937
+ Secp256k1.sign({
2938
+ payload: KeyAuthorization.getSignPayload(keyAuth),
2939
+ privateKey: root.privateKey,
2940
+ }),
2941
+ ),
2942
+ })
2943
+
2944
+ const nonce = await getTransactionCount(client, {
2945
+ address: root.address,
2946
+ blockTag: 'pending',
2947
+ })
2948
+
2949
+ const transaction = TxEnvelopeTempo.from({
2950
+ calls: [{ to: '0x0000000000000000000000000000000000000000' }],
2951
+ chainId,
2952
+ feeToken: '0x20c0000000000000000000000000000000000001',
2953
+ keyAuthorization: keyAuth_signed,
2954
+ nonce: BigInt(nonce),
2955
+ gas: 1_000_000n,
2956
+ maxFeePerGas: Value.fromGwei('20'),
2957
+ maxPriorityFeePerGas: Value.fromGwei('10'),
2958
+ })
2959
+
2960
+ const signature = Secp256k1.sign({
2961
+ payload: TxEnvelopeTempo.getSignPayload(transaction, {
2962
+ from: root.address,
2963
+ }),
2964
+ privateKey: accessPrivateKey,
2965
+ })
2966
+
2967
+ const serialized_signed = TxEnvelopeTempo.serialize(transaction, {
2968
+ signature: SignatureEnvelope.from({
2969
+ userAddress: root.address,
2970
+ inner: SignatureEnvelope.from(signature),
2971
+ type: 'keychain',
2972
+ }),
2973
+ })
2974
+
2975
+ const receipt = (await client
2976
+ .request({
2977
+ method: 'eth_sendRawTransactionSync',
2978
+ params: [serialized_signed],
2979
+ })
2980
+ .then((tx) => TransactionReceipt.fromRpc(tx as any)))!
2981
+ expect(receipt.status).toBe('success')
2982
+
2983
+ const response = await client
2984
+ .request({
2985
+ method: 'eth_getTransactionByHash',
2986
+ params: [receipt.transactionHash],
2987
+ })
2988
+ .then((tx) => Transaction.fromRpc(tx as any))
2989
+ if (!response) throw new Error()
2990
+
2991
+ expect(response.keyAuthorization?.isAdmin).toBeUndefined()
2992
+ expect(response.keyAuthorization?.account).toBeUndefined()
2993
+ },
2994
+ )
2665
2995
  })
package/version.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  /** @internal */
2
- export const version = '0.14.25'
2
+ export const version = '0.14.26'