Skip to content

Commit 95458ee

Browse files
committed
feat: add TransactionRequest.fromRpc
1 parent c165694 commit 95458ee

File tree

3 files changed

+166
-0
lines changed

3 files changed

+166
-0
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"ox": patch
3+
---
4+
5+
Added `TransactionRequest.fromRpc`

src/core/TransactionRequest.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,62 @@ export type TransactionRequest<
5353
/** RPC representation of a {@link ox#TransactionRequest.TransactionRequest}. */
5454
export type Rpc = TransactionRequest<Hex.Hex, Hex.Hex, string>
5555

56+
/**
57+
* Converts a {@link ox#TransactionRequest.Rpc} to a {@link ox#TransactionRequest.TransactionRequest}.
58+
*
59+
* @example
60+
* ```ts twoslash
61+
* import { TransactionRequest } from 'ox'
62+
*
63+
* const request = TransactionRequest.fromRpc({
64+
* to: '0x0000000000000000000000000000000000000000',
65+
* value: '0x2386f26fc10000',
66+
* })
67+
* ```
68+
*
69+
* @param request - The RPC request to convert.
70+
* @returns A transaction request.
71+
*/
72+
export function fromRpc(request: Rpc): TransactionRequest {
73+
const request_ = request as TransactionRequest
74+
75+
if (typeof request.authorizationList !== 'undefined')
76+
request_.authorizationList = Authorization.fromRpcList(
77+
request.authorizationList,
78+
)
79+
if (typeof request.chainId !== 'undefined')
80+
request_.chainId = Hex.toNumber(request.chainId)
81+
if (typeof request.gas !== 'undefined')
82+
request_.gas = Hex.toBigInt(request.gas)
83+
if (typeof request.gasPrice !== 'undefined')
84+
request_.gasPrice = Hex.toBigInt(request.gasPrice)
85+
if (typeof request.maxFeePerBlobGas !== 'undefined')
86+
request_.maxFeePerBlobGas = Hex.toBigInt(request.maxFeePerBlobGas)
87+
if (typeof request.maxFeePerGas !== 'undefined')
88+
request_.maxFeePerGas = Hex.toBigInt(request.maxFeePerGas)
89+
if (typeof request.maxPriorityFeePerGas !== 'undefined')
90+
request_.maxPriorityFeePerGas = Hex.toBigInt(request.maxPriorityFeePerGas)
91+
if (typeof request.nonce !== 'undefined')
92+
request_.nonce = Hex.toBigInt(request.nonce)
93+
if (typeof request.type !== 'undefined')
94+
request_.type =
95+
Transaction.fromRpcType[
96+
request.type as keyof typeof Transaction.fromRpcType
97+
] || request.type
98+
if (typeof request.value !== 'undefined')
99+
request_.value = Hex.toBigInt(request.value)
100+
101+
return request_
102+
}
103+
104+
export declare namespace fromRpc {
105+
export type ErrorType =
106+
| Authorization.fromRpcList.ErrorType
107+
| Hex.toNumber.ErrorType
108+
| Hex.toBigInt.ErrorType
109+
| Errors.GlobalErrorType
110+
}
111+
56112
/**
57113
* Converts a {@link ox#TransactionRequest.TransactionRequest} to a {@link ox#TransactionRequest.Rpc}.
58114
*

src/core/_test/TransactionRequest.test.ts

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,114 @@ describe('toRpc', () => {
9494
})
9595
})
9696

97+
describe('fromRpc', () => {
98+
test('default', () => {
99+
const request = TransactionRequest.fromRpc({
100+
to: '0x0000000000000000000000000000000000000000',
101+
value: '0x2386f26fc10000',
102+
})
103+
expect(request).toMatchInlineSnapshot(`
104+
{
105+
"to": "0x0000000000000000000000000000000000000000",
106+
"value": 10000000000000000n,
107+
}
108+
`)
109+
})
110+
111+
test('behavior: all', () => {
112+
const request = TransactionRequest.fromRpc({
113+
accessList: [],
114+
authorizationList: [],
115+
blobs: ['0xdeadbeef'],
116+
blobVersionedHashes: ['0xdeadbeef'],
117+
chainId: '0x1',
118+
data: '0xdeadbeef',
119+
from: '0x0000000000000000000000000000000000000000',
120+
gas: '0xf4240',
121+
gasPrice: '0x3b9aca00',
122+
maxFeePerBlobGas: '0x3b9aca00',
123+
maxFeePerGas: '0x3b9aca00',
124+
maxPriorityFeePerGas: '0x3b9aca00',
125+
nonce: '0x1',
126+
to: '0x0000000000000000000000000000000000000000',
127+
type: '0x2',
128+
value: '0x3b9aca00',
129+
})
130+
expect(request).toMatchInlineSnapshot(`
131+
{
132+
"accessList": [],
133+
"authorizationList": [],
134+
"blobVersionedHashes": [
135+
"0xdeadbeef",
136+
],
137+
"blobs": [
138+
"0xdeadbeef",
139+
],
140+
"chainId": 1,
141+
"data": "0xdeadbeef",
142+
"from": "0x0000000000000000000000000000000000000000",
143+
"gas": 1000000n,
144+
"gasPrice": 1000000000n,
145+
"maxFeePerBlobGas": 1000000000n,
146+
"maxFeePerGas": 1000000000n,
147+
"maxPriorityFeePerGas": 1000000000n,
148+
"nonce": 1n,
149+
"to": "0x0000000000000000000000000000000000000000",
150+
"type": "eip1559",
151+
"value": 1000000000n,
152+
}
153+
`)
154+
})
155+
156+
test('behavior: input', () => {
157+
const request = TransactionRequest.fromRpc({
158+
input: '0xdeadbeef',
159+
})
160+
expect(request).toMatchInlineSnapshot(`
161+
{
162+
"input": "0xdeadbeef",
163+
}
164+
`)
165+
})
166+
167+
test('behavior: empty', () => {
168+
const request = TransactionRequest.fromRpc({})
169+
expect(request).toMatchInlineSnapshot('{}')
170+
})
171+
172+
test('behavior: roundtrip', () => {
173+
const original: TransactionRequest.TransactionRequest = {
174+
accessList: [],
175+
authorizationList: [],
176+
blobs: ['0xdeadbeef'],
177+
blobVersionedHashes: ['0xdeadbeef'],
178+
chainId: 1,
179+
data: '0xdeadbeef',
180+
from: '0x0000000000000000000000000000000000000000',
181+
gas: 1000000n,
182+
gasPrice: 1000000000n,
183+
maxFeePerBlobGas: 1000000000n,
184+
maxFeePerGas: 1000000000n,
185+
maxPriorityFeePerGas: 1000000000n,
186+
nonce: 1n,
187+
to: '0x0000000000000000000000000000000000000000',
188+
type: 'eip1559',
189+
value: 1000000000n,
190+
}
191+
const rpc = TransactionRequest.toRpc(original)
192+
const converted = TransactionRequest.fromRpc(rpc)
193+
194+
expect(converted).toEqual({
195+
...original,
196+
input: '0xdeadbeef',
197+
})
198+
})
199+
})
200+
97201
test('exports', () => {
98202
expect(Object.keys(TransactionRequest)).toMatchInlineSnapshot(`
99203
[
204+
"fromRpc",
100205
"toRpc",
101206
]
102207
`)

0 commit comments

Comments
 (0)