viem 0.4.0-main.20230429T103734 → 0.4.0-main.20230430T000813

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.
Files changed (73) hide show
  1. package/dist/cjs/actions/public/call.js +12 -1
  2. package/dist/cjs/actions/public/call.js.map +1 -1
  3. package/dist/cjs/errors/base.js +17 -0
  4. package/dist/cjs/errors/base.js.map +1 -1
  5. package/dist/cjs/errors/ccip.js +68 -0
  6. package/dist/cjs/errors/ccip.js.map +1 -0
  7. package/dist/cjs/errors/index.js +7 -3
  8. package/dist/cjs/errors/index.js.map +1 -1
  9. package/dist/cjs/errors/request.js +1 -1
  10. package/dist/cjs/errors/request.js.map +1 -1
  11. package/dist/cjs/errors/version.js +1 -1
  12. package/dist/cjs/index.js +7 -2
  13. package/dist/cjs/index.js.map +1 -1
  14. package/dist/cjs/utils/ccip.js +97 -0
  15. package/dist/cjs/utils/ccip.js.map +1 -0
  16. package/dist/cjs/utils/errors/getContractError.js +1 -5
  17. package/dist/cjs/utils/errors/getContractError.js.map +1 -1
  18. package/dist/cjs/utils/errors/getNodeError.js +1 -1
  19. package/dist/cjs/utils/errors/getNodeError.js.map +1 -1
  20. package/dist/cjs/utils/index.js +8 -3
  21. package/dist/cjs/utils/index.js.map +1 -1
  22. package/dist/esm/actions/public/call.js +12 -2
  23. package/dist/esm/actions/public/call.js.map +1 -1
  24. package/dist/esm/errors/base.js +17 -0
  25. package/dist/esm/errors/base.js.map +1 -1
  26. package/dist/esm/errors/ccip.js +62 -0
  27. package/dist/esm/errors/ccip.js.map +1 -0
  28. package/dist/esm/errors/index.js +1 -0
  29. package/dist/esm/errors/index.js.map +1 -1
  30. package/dist/esm/errors/request.js +1 -1
  31. package/dist/esm/errors/request.js.map +1 -1
  32. package/dist/esm/errors/version.js +1 -1
  33. package/dist/esm/index.js +1 -1
  34. package/dist/esm/index.js.map +1 -1
  35. package/dist/esm/utils/ccip.js +92 -0
  36. package/dist/esm/utils/ccip.js.map +1 -0
  37. package/dist/esm/utils/errors/getContractError.js +3 -7
  38. package/dist/esm/utils/errors/getContractError.js.map +1 -1
  39. package/dist/esm/utils/errors/getNodeError.js +1 -1
  40. package/dist/esm/utils/errors/getNodeError.js.map +1 -1
  41. package/dist/esm/utils/index.js +1 -0
  42. package/dist/esm/utils/index.js.map +1 -1
  43. package/dist/types/actions/public/call.d.ts +1 -0
  44. package/dist/types/actions/public/call.d.ts.map +1 -1
  45. package/dist/types/errors/base.d.ts +2 -0
  46. package/dist/types/errors/base.d.ts.map +1 -1
  47. package/dist/types/errors/ccip.d.ts +29 -0
  48. package/dist/types/errors/ccip.d.ts.map +1 -0
  49. package/dist/types/errors/index.d.ts +1 -0
  50. package/dist/types/errors/index.d.ts.map +1 -1
  51. package/dist/types/errors/request.d.ts +2 -2
  52. package/dist/types/errors/request.d.ts.map +1 -1
  53. package/dist/types/errors/version.d.ts +1 -1
  54. package/dist/types/index.d.ts +1 -1
  55. package/dist/types/index.d.ts.map +1 -1
  56. package/dist/types/utils/ccip.d.ts +35 -0
  57. package/dist/types/utils/ccip.d.ts.map +1 -0
  58. package/dist/types/utils/errors/getContractError.d.ts.map +1 -1
  59. package/dist/types/utils/formatters/transaction.d.ts +1 -1
  60. package/dist/types/utils/index.d.ts +1 -0
  61. package/dist/types/utils/index.d.ts.map +1 -1
  62. package/package.json +1 -1
  63. package/src/actions/public/call.ts +12 -1
  64. package/src/errors/base.ts +10 -0
  65. package/src/errors/ccip.ts +74 -0
  66. package/src/errors/index.ts +6 -0
  67. package/src/errors/request.ts +3 -3
  68. package/src/errors/version.ts +1 -1
  69. package/src/index.ts +4 -0
  70. package/src/utils/ccip.ts +136 -0
  71. package/src/utils/errors/getContractError.ts +1 -7
  72. package/src/utils/errors/getNodeError.ts +1 -1
  73. package/src/utils/index.ts +7 -0
@@ -10,7 +10,7 @@ export declare const transactionType: {
10
10
  export declare function formatTransaction(transaction: Partial<RpcTransaction>): Transaction;
11
11
  export declare const defineTransaction: <TFormat extends Formatter<Partial<RpcTransaction>, Partial<Transaction> & {
12
12
  [key: string]: unknown;
13
- }>, TExclude extends ("from" | "gas" | "nonce" | "to" | "value" | "type" | "blockNumber" | "blockHash" | "chainId" | "hash" | "input" | "r" | "s" | "transactionIndex" | "v" | "gasPrice" | "maxFeePerGas" | "maxPriorityFeePerGas" | "accessList")[] = []>({ exclude, format: formatOverride, }: {
13
+ }>, TExclude extends ("from" | "gas" | "nonce" | "to" | "value" | "type" | "gasPrice" | "maxFeePerGas" | "maxPriorityFeePerGas" | "accessList" | "blockNumber" | "blockHash" | "transactionIndex" | "chainId" | "r" | "s" | "v" | "hash" | "input")[] = []>({ exclude, format: formatOverride, }: {
14
14
  exclude?: TExclude | undefined;
15
15
  format?: TFormat | undefined;
16
16
  }) => (data: Partial<RpcTransaction> & {
@@ -4,6 +4,7 @@ export { parseAccount, publicKeyToAddress } from './accounts.js';
4
4
  export type { GetContractAddressOptions, GetCreate2AddressOptions, GetCreateAddressOptions, } from './address/index.js';
5
5
  export { getAddress, getContractAddress, getCreateAddress, getCreate2Address, isAddress, isAddressEqual, } from './address/index.js';
6
6
  export { buildRequest } from './buildRequest.js';
7
+ export { ccipFetch, offchainLookup, offchainLookupAbiItem, offchainLookupSignature, } from './ccip.js';
7
8
  export { defineChain, getChainContractAddress } from './chain.js';
8
9
  export { extractFunctionName, extractFunctionParams, extractFunctionType, extractFunctionParts, } from './contract/index.js';
9
10
  export { concat, concatBytes, concatHex, isBytes, isHex, pad, padBytes, padHex, size, slice, sliceBytes, sliceHex, trim, } from './data/index.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -12,7 +12,7 @@
12
12
  "isomorphic-ws": "5.0.0",
13
13
  "ws": "8.12.0"
14
14
  },
15
- "version": "0.4.0-main.20230429T103734",
15
+ "version": "0.4.0-main.20230430T000813",
16
16
  "files": [
17
17
  "dist",
18
18
  "!dist/**/*.tsbuildinfo",
@@ -1,7 +1,7 @@
1
1
  import type { PublicClient, Transport } from '../../clients/index.js'
2
2
  import { aggregate3Signature, multicall3Abi } from '../../constants/index.js'
3
- import type { BaseError } from '../../errors/index.js'
4
3
  import {
4
+ BaseError,
5
5
  ChainDoesNotSupportContract,
6
6
  ClientChainNotConfiguredError,
7
7
  RawContractError,
@@ -30,6 +30,7 @@ import {
30
30
  getCallError,
31
31
  getChainContractAddress,
32
32
  numberToHex,
33
+ offchainLookupSignature,
33
34
  parseAccount,
34
35
  } from '../../utils/index.js'
35
36
  import { createBatchScheduler } from '../../utils/promise/createBatchScheduler.js'
@@ -159,6 +160,11 @@ export async function call<TChain extends Chain | undefined>(
159
160
  if (response === '0x') return { data: undefined }
160
161
  return { data: response }
161
162
  } catch (err) {
163
+ const data = getRevertErrorData(err)
164
+ if (data?.slice(0, 10) === offchainLookupSignature && to) {
165
+ const { offchainLookup } = await import('../../utils/ccip.js')
166
+ return { data: await offchainLookup(client, { data, to }) }
167
+ }
162
168
  throw getCallError(err as BaseError, {
163
169
  ...args,
164
170
  account,
@@ -272,3 +278,8 @@ async function scheduleMulticall<TChain extends Chain | undefined>(
272
278
  if (returnData === '0x') return { data: undefined }
273
279
  return { data: returnData }
274
280
  }
281
+
282
+ export function getRevertErrorData(err: unknown) {
283
+ if (!(err instanceof BaseError)) return undefined
284
+ return (err.walk() as { data?: Hex })?.data
285
+ }
@@ -59,4 +59,14 @@ export class BaseError extends Error {
59
59
  this.metaMessages = args.metaMessages
60
60
  this.shortMessage = shortMessage
61
61
  }
62
+
63
+ walk(fn?: (err: unknown) => boolean) {
64
+ return this.#walk(this, fn)
65
+ }
66
+
67
+ #walk(err: unknown, fn?: (err: unknown) => boolean): unknown {
68
+ if (fn?.(err)) return err
69
+ if ((err as Error).cause) return this.#walk((err as Error).cause, fn)
70
+ return err
71
+ }
62
72
  }
@@ -0,0 +1,74 @@
1
+ import type { Address } from 'abitype'
2
+ import { BaseError } from './base.js'
3
+ import type { Hex } from '../types/index.js'
4
+ import { getUrl } from './utils.js'
5
+
6
+ export class OffchainLookupError extends BaseError {
7
+ override name = 'OffchainLookupError'
8
+ constructor({
9
+ callbackSelector,
10
+ cause,
11
+ data,
12
+ extraData,
13
+ sender,
14
+ urls,
15
+ }: {
16
+ callbackSelector: Hex
17
+ cause: BaseError
18
+ data: Hex
19
+ extraData: Hex
20
+ sender: Address
21
+ urls: readonly string[]
22
+ }) {
23
+ super(
24
+ cause.shortMessage ||
25
+ 'An error occurred while fetching for an offchain result.',
26
+ {
27
+ cause,
28
+ metaMessages: [
29
+ ...(cause.metaMessages || []),
30
+ cause.metaMessages?.length ? '' : [],
31
+ 'Offchain Gateway Call:',
32
+ urls && [
33
+ ' Gateway URL(s):',
34
+ ...urls.map((url) => ` ${getUrl(url)}`),
35
+ ],
36
+ ` Sender: ${sender}`,
37
+ ` Data: ${data}`,
38
+ ` Callback selector: ${callbackSelector}`,
39
+ ` Extra data: ${extraData}`,
40
+ ].flat(),
41
+ },
42
+ )
43
+ }
44
+ }
45
+
46
+ export class OffchainLookupResponseMalformedError extends BaseError {
47
+ override name = 'OffchainLookupResponseMalformedError'
48
+ constructor({ result, url }: { result: any; url: string }) {
49
+ super(
50
+ 'Offchain gateway response is malformed. Response data must be a hex value.',
51
+ {
52
+ metaMessages: [
53
+ `Gateway URL: ${getUrl(url)}`,
54
+ `Response: ${JSON.stringify(result)}`,
55
+ ],
56
+ },
57
+ )
58
+ }
59
+ }
60
+
61
+ export class OffchainLookupSenderMismatchError extends BaseError {
62
+ override name = 'OffchainLookupSenderMismatchError'
63
+ constructor({ sender, to }: { sender: Address; to: Address }) {
64
+ super(
65
+ 'Reverted sender address does not match target contract address (`to`).',
66
+ {
67
+ metaMessages: [
68
+ `Contract address: ${to}`,
69
+ `OffchainLookup sender address: ${sender}`,
70
+ ],
71
+ },
72
+ )
73
+ }
74
+ }
@@ -41,6 +41,12 @@ export {
41
41
  InvalidChainIdError,
42
42
  } from './chain.js'
43
43
 
44
+ export {
45
+ OffchainLookupError,
46
+ OffchainLookupResponseMalformedError,
47
+ OffchainLookupSenderMismatchError,
48
+ } from './ccip.js'
49
+
44
50
  export {
45
51
  CallExecutionError,
46
52
  ContractFunctionExecutionError,
@@ -5,7 +5,7 @@ import { getUrl } from './utils.js'
5
5
  export class HttpRequestError extends BaseError {
6
6
  override name = 'HttpRequestError'
7
7
 
8
- body: { [key: string]: unknown }
8
+ body?: { [key: string]: unknown }
9
9
  headers?: Headers
10
10
  status?: number
11
11
  url: string
@@ -17,7 +17,7 @@ export class HttpRequestError extends BaseError {
17
17
  status,
18
18
  url,
19
19
  }: {
20
- body: { [key: string]: unknown }
20
+ body?: { [key: string]: unknown }
21
21
  details?: string
22
22
  headers?: Headers
23
23
  status?: number
@@ -28,7 +28,7 @@ export class HttpRequestError extends BaseError {
28
28
  metaMessages: [
29
29
  status && `Status: ${status}`,
30
30
  `URL: ${getUrl(url)}`,
31
- `Request body: ${stringify(body)}`,
31
+ body && `Request body: ${stringify(body)}`,
32
32
  ].filter(Boolean) as string[],
33
33
  })
34
34
  this.body = body
@@ -1 +1 @@
1
- export const version = '0.4.0-main.20230429T103734'
1
+ export const version = '0.4.0-main.20230430T000813'
package/src/index.ts CHANGED
@@ -399,6 +399,7 @@ export {
399
399
  bytesToHex,
400
400
  bytesToNumber,
401
401
  bytesToString,
402
+ ccipFetch,
402
403
  concat,
403
404
  concatBytes,
404
405
  concatHex,
@@ -453,6 +454,9 @@ export {
453
454
  keccak256,
454
455
  numberToBytes,
455
456
  numberToHex,
457
+ offchainLookup,
458
+ offchainLookupAbiItem,
459
+ offchainLookupSignature,
456
460
  pad,
457
461
  padBytes,
458
462
  padHex,
@@ -0,0 +1,136 @@
1
+ import { parseAbiItem, parseAbiParameters, type Address } from 'abitype'
2
+ import type { PublicClient, Transport } from '../clients/index.js'
3
+ import {
4
+ BaseError,
5
+ HttpRequestError,
6
+ OffchainLookupError,
7
+ OffchainLookupResponseMalformedError,
8
+ OffchainLookupSenderMismatchError,
9
+ } from '../errors/index.js'
10
+ import { call, type CallParameters } from '../public.js'
11
+ import type { Chain, GetErrorArgs, Hex } from '../types/index.js'
12
+ import { decodeErrorResult, encodeAbiParameters } from './abi/index.js'
13
+ import { isAddressEqual } from './address/index.js'
14
+ import { concat, isHex } from './data/index.js'
15
+ import { stringify } from './stringify.js'
16
+
17
+ export const offchainLookupSignature = '0x556f1830'
18
+ export const offchainLookupAbiItem = parseAbiItem(
19
+ 'error OffchainLookup(address sender, string[] urls, bytes callData, bytes4 callbackFunction, bytes extraData)',
20
+ )
21
+
22
+ export async function offchainLookup<TChain extends Chain | undefined>(
23
+ client: PublicClient<Transport, TChain>,
24
+ {
25
+ blockNumber,
26
+ blockTag,
27
+ data,
28
+ to,
29
+ }: Pick<CallParameters, 'blockNumber' | 'blockTag'> & {
30
+ data: Hex
31
+ to: Address
32
+ },
33
+ ): Promise<Hex> {
34
+ const { args } = decodeErrorResult({
35
+ data,
36
+ abi: [offchainLookupAbiItem],
37
+ }) as unknown as GetErrorArgs<
38
+ [typeof offchainLookupAbiItem],
39
+ 'OffchainLookup'
40
+ >
41
+ const [sender, urls, callData, callbackSelector, extraData] = args
42
+
43
+ try {
44
+ if (!isAddressEqual(to, sender))
45
+ throw new OffchainLookupSenderMismatchError({ sender, to })
46
+
47
+ const result = await ccipFetch({ data: callData, sender, urls })
48
+
49
+ const { data: data_ } = await call(client, {
50
+ blockNumber,
51
+ blockTag,
52
+ data: concat([
53
+ callbackSelector,
54
+ encodeAbiParameters(parseAbiParameters('bytes,bytes'), [
55
+ result,
56
+ extraData,
57
+ ]),
58
+ ]),
59
+ to,
60
+ } as CallParameters)
61
+
62
+ return data_!
63
+ } catch (err) {
64
+ throw new OffchainLookupError({
65
+ callbackSelector,
66
+ cause: err as BaseError,
67
+ data,
68
+ extraData,
69
+ sender,
70
+ urls,
71
+ })
72
+ }
73
+ }
74
+
75
+ export async function ccipFetch({
76
+ data,
77
+ sender,
78
+ urls,
79
+ }: { data: Hex; sender: Address; urls: readonly string[] }) {
80
+ let error = new Error('An unknown error occurred.')
81
+
82
+ for (let i = 0; i < urls.length; i++) {
83
+ const url = urls[i]
84
+ const method =
85
+ url.includes('{sender}') || url.includes('{data}') ? 'GET' : 'POST'
86
+ const body = method === 'POST' ? { data, sender } : undefined
87
+
88
+ try {
89
+ const response = await fetch(
90
+ url.replace('{sender}', sender).replace('{data}', data),
91
+ {
92
+ body: JSON.stringify(body),
93
+ method,
94
+ },
95
+ )
96
+
97
+ let result
98
+ if (
99
+ response.headers.get('Content-Type')?.startsWith('application/json')
100
+ ) {
101
+ result = (await response.json()).data
102
+ } else {
103
+ result = (await response.text()) as any
104
+ }
105
+
106
+ if (!response.ok) {
107
+ error = new HttpRequestError({
108
+ body,
109
+ details: stringify(result.error) || response.statusText,
110
+ headers: response.headers,
111
+ status: response.status,
112
+ url,
113
+ })
114
+ continue
115
+ }
116
+
117
+ if (!isHex(result)) {
118
+ error = new OffchainLookupResponseMalformedError({
119
+ result,
120
+ url,
121
+ })
122
+ continue
123
+ }
124
+
125
+ return result
126
+ } catch (err) {
127
+ error = new HttpRequestError({
128
+ body,
129
+ details: (err as Error).message,
130
+ url,
131
+ })
132
+ }
133
+ }
134
+
135
+ throw error
136
+ }
@@ -3,11 +3,9 @@ import type { BaseError } from '../../errors/index.js'
3
3
  import {
4
4
  AbiDecodingZeroDataError,
5
5
  ContractFunctionExecutionError,
6
- EstimateGasExecutionError,
7
6
  RawContractError,
8
7
  } from '../../errors/index.js'
9
8
  import {
10
- CallExecutionError,
11
9
  ContractFunctionRevertedError,
12
10
  ContractFunctionZeroDataError,
13
11
  } from '../../errors/contract.js'
@@ -36,11 +34,7 @@ export function getContractError(
36
34
  const { code, data, message, shortMessage } = (
37
35
  err instanceof RawContractError
38
36
  ? err
39
- : !(err.cause && 'data' in (err.cause as BaseError)) &&
40
- (err instanceof CallExecutionError ||
41
- err instanceof EstimateGasExecutionError)
42
- ? ((err.cause as BaseError)?.cause as BaseError)?.cause || {}
43
- : err.cause || {}
37
+ : err.walk((err) => 'data' in (err as Error))
44
38
  ) as RawContractError
45
39
 
46
40
  let cause = err
@@ -67,7 +67,7 @@ export function getNodeError(
67
67
  )
68
68
  return new ExecutionRevertedError({
69
69
  cause: err,
70
- message: (err.cause as BaseError).details,
70
+ message: (err.cause as BaseError).details || err.details,
71
71
  })
72
72
  return new UnknownNodeError({
73
73
  cause: (err.cause as BaseError).cause as BaseError,
@@ -60,6 +60,13 @@ export {
60
60
 
61
61
  export { buildRequest } from './buildRequest.js'
62
62
 
63
+ export {
64
+ ccipFetch,
65
+ offchainLookup,
66
+ offchainLookupAbiItem,
67
+ offchainLookupSignature,
68
+ } from './ccip.js'
69
+
63
70
  export { defineChain, getChainContractAddress } from './chain.js'
64
71
 
65
72
  export {