-
-
Notifications
You must be signed in to change notification settings - Fork 36
Expand file tree
/
Copy pathTransactionRequest.ts
More file actions
163 lines (154 loc) · 5.33 KB
/
TransactionRequest.ts
File metadata and controls
163 lines (154 loc) · 5.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
import type * as Errors from '../core/Errors.js'
import * as Hex from '../core/Hex.js'
import type { Compute } from '../core/internal/types.js'
import * as ox_TransactionRequest from '../core/TransactionRequest.js'
import * as AuthorizationTempo from './AuthorizationTempo.js'
import * as KeyAuthorization from './KeyAuthorization.js'
import * as TempoAddress from './TempoAddress.js'
import * as TokenId from './TokenId.js'
import * as Transaction from './Transaction.js'
import type { Call } from './TxEnvelopeTempo.js'
type KeyType = 'secp256k1' | 'p256' | 'webAuthn'
/**
* A Transaction Request that is generic to all transaction types.
*
* Extends the [Execution API specification](https://github.com/ethereum/execution-apis/blob/4aca1d7a3e5aab24c8f6437131289ad386944eaa/src/schemas/transaction.yaml#L358-L423)
* with Tempo-specific fields for batched calls, fee tokens, access keys, and scheduled execution.
*
* @see {@link https://docs.tempo.xyz/protocol/transactions}
*/
export type TransactionRequest<
bigintType = bigint,
numberType = number,
type extends string = string,
> = Compute<
Omit<
ox_TransactionRequest.TransactionRequest<bigintType, numberType, type>,
'authorizationList'
> & {
authorizationList?:
| AuthorizationTempo.ListSigned<bigintType, numberType>
| undefined
calls?: readonly Call<bigintType, TempoAddress.Address>[] | undefined
keyAuthorization?: KeyAuthorization.KeyAuthorization<true> | undefined
keyData?: Hex.Hex | undefined
keyType?: KeyType | undefined
feeToken?: TokenId.TokenIdOrAddress | undefined
nonceKey?: 'random' | bigintType | undefined
validBefore?: numberType | undefined
validAfter?: numberType | undefined
}
>
/** RPC representation of a {@link ox#TransactionRequest.TransactionRequest}. */
export type Rpc = Omit<
TransactionRequest<Hex.Hex, Hex.Hex, string>,
'authorizationList' | 'keyAuthorization'
> & {
authorizationList?: AuthorizationTempo.ListRpc | undefined
keyAuthorization?: KeyAuthorization.Rpc | undefined
nonceKey?: Hex.Hex | undefined
}
/**
* Converts a {@link ox#TransactionRequest.TransactionRequest} to a {@link ox#TransactionRequest.Rpc}.
*
* @see {@link https://docs.tempo.xyz/protocol/transactions}
*
* @example
* ```ts twoslash
* import { Value } from 'ox'
* import { TransactionRequest } from 'ox/tempo'
*
* const request = TransactionRequest.toRpc({
* calls: [{
* data: '0xdeadbeef',
* to: '0xcafebabecafebabecafebabecafebabecafebabe',
* }],
* feeToken: '0x20c0000000000000000000000000000000000000',
* })
* ```
*
* @example
* ### Using with a Provider
*
* You can use {@link ox#Provider.(from:function)} to instantiate an EIP-1193 Provider and
* send a transaction to the Wallet using the `eth_sendTransaction` method.
*
* ```ts twoslash
* import 'ox/window'
* import { Provider, Value } from 'ox'
* import { TransactionRequest } from 'ox/tempo'
*
* const provider = Provider.from(window.ethereum!)
*
* const request = TransactionRequest.toRpc({
* calls: [{
* data: '0xdeadbeef',
* to: '0xcafebabecafebabecafebabecafebabecafebabe',
* }],
* feeToken: '0x20c0000000000000000000000000000000000000',
* })
*
* const hash = await provider.request({ // [!code focus]
* method: 'eth_sendTransaction', // [!code focus]
* params: [request], // [!code focus]
* }) // [!code focus]
* ```
*
* @param request - The request to convert.
* @returns An RPC request.
*/
export function toRpc(request: TransactionRequest): Rpc {
const request_rpc = ox_TransactionRequest.toRpc({
...request,
authorizationList: undefined,
}) as Rpc
if (request.authorizationList)
request_rpc.authorizationList = AuthorizationTempo.toRpcList(
request.authorizationList,
)
if (request.calls)
request_rpc.calls = request.calls.map((call) => ({
to: call.to ? TempoAddress.resolve(call.to) : call.to,
value: call.value ? Hex.fromNumber(call.value) : '0x',
data: call.data ?? '0x',
}))
if (typeof request.feeToken !== 'undefined')
request_rpc.feeToken = TokenId.toAddress(request.feeToken)
if (request.keyAuthorization)
request_rpc.keyAuthorization = KeyAuthorization.toRpc(
request.keyAuthorization,
)
if (typeof request.validBefore !== 'undefined')
request_rpc.validBefore = Hex.fromNumber(request.validBefore)
if (typeof request.validAfter !== 'undefined')
request_rpc.validAfter = Hex.fromNumber(request.validAfter)
const nonceKey = (() => {
if (request.nonceKey === 'random') return Hex.random(6)
if (typeof request.nonceKey === 'bigint')
return Hex.fromNumber(request.nonceKey)
return undefined
})()
if (nonceKey) request_rpc.nonceKey = nonceKey
if (
typeof request.calls !== 'undefined' ||
typeof request.feeToken !== 'undefined' ||
typeof request.keyAuthorization !== 'undefined' ||
typeof request.nonceKey !== 'undefined' ||
typeof request.validBefore !== 'undefined' ||
typeof request.validAfter !== 'undefined' ||
request.type === 'tempo'
) {
request_rpc.type = Transaction.toRpcType.tempo
delete request_rpc.data
delete request_rpc.input
delete request_rpc.to
delete request_rpc.value
}
return request_rpc
}
export declare namespace toRpc {
export type ErrorType =
| AuthorizationTempo.toRpcList.ErrorType
| Hex.fromNumber.ErrorType
| Errors.GlobalErrorType
}