@alchemy/wallet-apis 0.0.0-alpha.19 → 0.0.0-alpha.21
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/dist/esm/actions/formatSign.js +3 -4
- package/dist/esm/actions/formatSign.js.map +1 -1
- package/dist/esm/actions/grantPermissions.js +3 -4
- package/dist/esm/actions/grantPermissions.js.map +1 -1
- package/dist/esm/actions/listAccounts.js +3 -4
- package/dist/esm/actions/listAccounts.js.map +1 -1
- package/dist/esm/actions/prepareCalls.d.ts +14 -3
- package/dist/esm/actions/prepareCalls.js +19 -5
- package/dist/esm/actions/prepareCalls.js.map +1 -1
- package/dist/esm/actions/prepareSign.js +3 -4
- package/dist/esm/actions/prepareSign.js.map +1 -1
- package/dist/esm/actions/requestAccount.js +3 -4
- package/dist/esm/actions/requestAccount.js.map +1 -1
- package/dist/esm/actions/sendCalls.js +2 -5
- package/dist/esm/actions/sendCalls.js.map +1 -1
- package/dist/esm/actions/sendPreparedCalls.js +3 -4
- package/dist/esm/actions/sendPreparedCalls.js.map +1 -1
- package/dist/esm/experimental/actions/requestQuoteV0.js +3 -4
- package/dist/esm/experimental/actions/requestQuoteV0.js.map +1 -1
- package/dist/esm/utils/capabilities.d.ts +14 -7
- package/dist/esm/utils/capabilities.js +3 -2
- package/dist/esm/utils/capabilities.js.map +1 -1
- package/dist/esm/utils/schema.d.ts +3 -1
- package/dist/esm/utils/schema.js +58 -0
- package/dist/esm/utils/schema.js.map +1 -1
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/esm/version.js.map +1 -1
- package/dist/types/actions/formatSign.d.ts.map +1 -1
- package/dist/types/actions/grantPermissions.d.ts.map +1 -1
- package/dist/types/actions/listAccounts.d.ts.map +1 -1
- package/dist/types/actions/prepareCalls.d.ts +14 -3
- package/dist/types/actions/prepareCalls.d.ts.map +1 -1
- package/dist/types/actions/prepareSign.d.ts.map +1 -1
- package/dist/types/actions/requestAccount.d.ts.map +1 -1
- package/dist/types/actions/sendCalls.d.ts.map +1 -1
- package/dist/types/actions/sendPreparedCalls.d.ts.map +1 -1
- package/dist/types/experimental/actions/requestQuoteV0.d.ts.map +1 -1
- package/dist/types/utils/capabilities.d.ts +14 -7
- package/dist/types/utils/capabilities.d.ts.map +1 -1
- package/dist/types/utils/schema.d.ts +3 -1
- package/dist/types/utils/schema.d.ts.map +1 -1
- package/dist/types/version.d.ts +1 -1
- package/package.json +4 -4
- package/src/actions/formatSign.ts +5 -4
- package/src/actions/grantPermissions.ts +9 -11
- package/src/actions/listAccounts.ts +5 -7
- package/src/actions/prepareCalls.ts +42 -6
- package/src/actions/prepareSign.ts +5 -4
- package/src/actions/requestAccount.ts +8 -7
- package/src/actions/sendCalls.ts +2 -8
- package/src/actions/sendPreparedCalls.ts +4 -6
- package/src/experimental/actions/requestQuoteV0.ts +5 -4
- package/src/utils/capabilities.ts +23 -11
- package/src/utils/schema.ts +79 -1
- package/src/version.ts +1 -1
|
@@ -5,8 +5,12 @@ import deepEqual from "deep-equal";
|
|
|
5
5
|
import type { DistributiveOmit, InnerWalletApiClient } from "../types";
|
|
6
6
|
import { LOGGER } from "../logger.js";
|
|
7
7
|
import { isLocalAccount } from "../utils/assertions.js";
|
|
8
|
-
import {
|
|
9
|
-
|
|
8
|
+
import {
|
|
9
|
+
methodSchema,
|
|
10
|
+
encode,
|
|
11
|
+
decode,
|
|
12
|
+
type MethodParams,
|
|
13
|
+
} from "../utils/schema.js";
|
|
10
14
|
|
|
11
15
|
const schema = methodSchema(MethodSchema);
|
|
12
16
|
type BaseRequestAccountParams = MethodParams<typeof MethodSchema>;
|
|
@@ -90,17 +94,14 @@ export async function requestAccount(
|
|
|
90
94
|
};
|
|
91
95
|
}
|
|
92
96
|
|
|
93
|
-
const rpcParams =
|
|
94
|
-
schema.request,
|
|
95
|
-
args satisfies BaseRequestAccountParams,
|
|
96
|
-
);
|
|
97
|
+
const rpcParams = encode(schema.request, args);
|
|
97
98
|
|
|
98
99
|
const rpcResp = await client.request({
|
|
99
100
|
method: "wallet_requestAccount",
|
|
100
101
|
params: [rpcParams],
|
|
101
102
|
});
|
|
102
103
|
|
|
103
|
-
const resp =
|
|
104
|
+
const resp = decode(schema.response, rpcResp);
|
|
104
105
|
|
|
105
106
|
client.internal?.setAccount({
|
|
106
107
|
address: resp.accountAddress,
|
package/src/actions/sendCalls.ts
CHANGED
|
@@ -8,10 +8,7 @@ import {
|
|
|
8
8
|
} from "./sendPreparedCalls.js";
|
|
9
9
|
import { LOGGER } from "../logger.js";
|
|
10
10
|
import { signSignatureRequest } from "./signSignatureRequest.js";
|
|
11
|
-
import {
|
|
12
|
-
extractCapabilitiesForSending,
|
|
13
|
-
fromRpcCapabilities,
|
|
14
|
-
} from "../utils/capabilities.js";
|
|
11
|
+
import { extractCapabilitiesForSending } from "../utils/capabilities.js";
|
|
15
12
|
|
|
16
13
|
export type SendCallsParams = Prettify<
|
|
17
14
|
DistributiveOmit<PrepareCallsParams, "chainId"> & {
|
|
@@ -77,10 +74,7 @@ export async function sendCalls(
|
|
|
77
74
|
);
|
|
78
75
|
|
|
79
76
|
const secondCallParams = {
|
|
80
|
-
|
|
81
|
-
calls: calls.modifiedRequest.calls,
|
|
82
|
-
chainId: calls.modifiedRequest.chainId,
|
|
83
|
-
capabilities: fromRpcCapabilities(calls.modifiedRequest.capabilities),
|
|
77
|
+
...calls.modifiedRequest,
|
|
84
78
|
// WebAuthn signatures are not supported for paymaster permits (throws above).
|
|
85
79
|
paymasterPermitSignature: signature as Exclude<
|
|
86
80
|
typeof signature,
|
|
@@ -7,9 +7,10 @@ import {
|
|
|
7
7
|
type WithCapabilities,
|
|
8
8
|
} from "../utils/capabilities.js";
|
|
9
9
|
import { wallet_sendPreparedCalls as MethodSchema } from "@alchemy/wallet-api-types/rpc";
|
|
10
|
-
import { Value } from "typebox/value";
|
|
11
10
|
import {
|
|
12
11
|
methodSchema,
|
|
12
|
+
encode,
|
|
13
|
+
decode,
|
|
13
14
|
type MethodParams,
|
|
14
15
|
type MethodResponse,
|
|
15
16
|
} from "../utils/schema.js";
|
|
@@ -79,10 +80,7 @@ export async function sendPreparedCalls(
|
|
|
79
80
|
capabilities: toRpcCapabilities(capabilities),
|
|
80
81
|
};
|
|
81
82
|
|
|
82
|
-
const rpcParams =
|
|
83
|
-
schema.request,
|
|
84
|
-
fullParams satisfies BaseSendPreparedCallsParams,
|
|
85
|
-
);
|
|
83
|
+
const rpcParams = encode(schema.request, fullParams);
|
|
86
84
|
|
|
87
85
|
const rpcResp = await client.request({
|
|
88
86
|
method: "wallet_sendPreparedCalls",
|
|
@@ -90,5 +88,5 @@ export async function sendPreparedCalls(
|
|
|
90
88
|
});
|
|
91
89
|
|
|
92
90
|
LOGGER.debug("sendPreparedCalls:done");
|
|
93
|
-
return
|
|
91
|
+
return decode(schema.response, rpcResp);
|
|
94
92
|
}
|
|
@@ -7,9 +7,10 @@ import {
|
|
|
7
7
|
} from "../../utils/capabilities.js";
|
|
8
8
|
import { resolveAddress, type AccountParam } from "../../utils/resolve.js";
|
|
9
9
|
import { wallet_requestQuote_v0 as MethodSchema } from "@alchemy/wallet-api-types/rpc";
|
|
10
|
-
import { Value } from "typebox/value";
|
|
11
10
|
import {
|
|
12
11
|
methodSchema,
|
|
12
|
+
encode,
|
|
13
|
+
decode,
|
|
13
14
|
type MethodParams,
|
|
14
15
|
type MethodResponse,
|
|
15
16
|
} from "../../utils/schema.js";
|
|
@@ -84,17 +85,17 @@ export async function requestQuoteV0(
|
|
|
84
85
|
);
|
|
85
86
|
|
|
86
87
|
const { account: _, chainId: __, ...rest } = params;
|
|
87
|
-
const rpcParams =
|
|
88
|
+
const rpcParams = encode(schema.request, {
|
|
88
89
|
...rest,
|
|
89
90
|
chainId: params.chainId ?? client.chain.id,
|
|
90
91
|
from,
|
|
91
92
|
...(capabilities && { capabilities: toRpcCapabilities(capabilities) }),
|
|
92
|
-
}
|
|
93
|
+
});
|
|
93
94
|
|
|
94
95
|
const rpcResp = await client.request({
|
|
95
96
|
method: "wallet_requestQuote_v0",
|
|
96
97
|
params: [rpcParams],
|
|
97
98
|
});
|
|
98
99
|
|
|
99
|
-
return
|
|
100
|
+
return decode(schema.response, rpcResp);
|
|
100
101
|
}
|
|
@@ -1,9 +1,21 @@
|
|
|
1
|
-
import
|
|
2
|
-
PrepareCallsCapabilities as
|
|
3
|
-
SendPreparedCallsCapabilities as
|
|
1
|
+
import {
|
|
2
|
+
PrepareCallsCapabilities as PrepareCallsCapabilitiesSchema,
|
|
3
|
+
SendPreparedCallsCapabilities as SendPreparedCallsCapabilitiesSchema,
|
|
4
4
|
} from "@alchemy/wallet-api-types/capabilities";
|
|
5
|
+
import type { StaticDecode } from "typebox";
|
|
5
6
|
import type { InnerWalletApiClient } from "../types.js";
|
|
6
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Decoded capabilities matching the schema shape (uses `paymasterService` key).
|
|
10
|
+
* `ResolveCapabilities` renames this to `paymaster` for client-facing types.
|
|
11
|
+
*/
|
|
12
|
+
type DecodedPrepareCallsCaps = StaticDecode<
|
|
13
|
+
typeof PrepareCallsCapabilitiesSchema
|
|
14
|
+
>;
|
|
15
|
+
type DecodedSendPreparedCallsCaps = StaticDecode<
|
|
16
|
+
typeof SendPreparedCallsCapabilitiesSchema
|
|
17
|
+
>;
|
|
18
|
+
|
|
7
19
|
/**
|
|
8
20
|
* Renames `paymasterService` (RPC) to `paymaster` in a capabilities type. This
|
|
9
21
|
* is because our RPC schema's paymasterService capability does not exactly match
|
|
@@ -17,10 +29,10 @@ type ResolveCapabilities<T> = T extends {
|
|
|
17
29
|
: T;
|
|
18
30
|
|
|
19
31
|
export type PrepareCallsCapabilities =
|
|
20
|
-
ResolveCapabilities<
|
|
32
|
+
ResolveCapabilities<DecodedPrepareCallsCaps>;
|
|
21
33
|
|
|
22
34
|
export type SendPreparedCallsCapabilities =
|
|
23
|
-
ResolveCapabilities<
|
|
35
|
+
ResolveCapabilities<DecodedSendPreparedCallsCaps>;
|
|
24
36
|
|
|
25
37
|
/**
|
|
26
38
|
* Transforms a type so that any `capabilities` field uses `paymaster`
|
|
@@ -36,7 +48,7 @@ export type WithCapabilities<T> = T extends {
|
|
|
36
48
|
|
|
37
49
|
function hasNoPaymasterField(
|
|
38
50
|
value: object,
|
|
39
|
-
): value is
|
|
51
|
+
): value is DecodedPrepareCallsCaps | DecodedSendPreparedCallsCaps {
|
|
40
52
|
return !("paymaster" in value);
|
|
41
53
|
}
|
|
42
54
|
|
|
@@ -51,14 +63,14 @@ function hasNoPaymasterServiceField(
|
|
|
51
63
|
* for use with Value.Encode before sending to the RPC.
|
|
52
64
|
*
|
|
53
65
|
* @param {PrepareCallsCapabilities | SendPreparedCallsCapabilities | undefined} capabilities - Capabilities object containing a `paymaster` field
|
|
54
|
-
* @returns {
|
|
66
|
+
* @returns {DecodedPrepareCallsCaps | DecodedSendPreparedCallsCaps | undefined} RPC capabilities with `paymasterService`, or undefined if input is undefined
|
|
55
67
|
*/
|
|
56
68
|
export function toRpcCapabilities(
|
|
57
69
|
capabilities:
|
|
58
70
|
| PrepareCallsCapabilities
|
|
59
71
|
| SendPreparedCallsCapabilities
|
|
60
72
|
| undefined,
|
|
61
|
-
):
|
|
73
|
+
): DecodedPrepareCallsCaps | DecodedSendPreparedCallsCaps | undefined {
|
|
62
74
|
if (!capabilities) return undefined;
|
|
63
75
|
const { paymaster, ...rest } = capabilities;
|
|
64
76
|
const result =
|
|
@@ -73,13 +85,13 @@ export function toRpcCapabilities(
|
|
|
73
85
|
* Converts RPC capabilities (with `paymasterService`) from Value.Decode
|
|
74
86
|
* to capabilities (with `paymaster`).
|
|
75
87
|
*
|
|
76
|
-
* @param {
|
|
88
|
+
* @param {DecodedPrepareCallsCaps | DecodedSendPreparedCallsCaps | undefined} capabilities - RPC capabilities object containing a `paymasterService` field
|
|
77
89
|
* @returns {PrepareCallsCapabilities | SendPreparedCallsCapabilities | undefined} Capabilities with `paymaster`, or undefined if input is undefined
|
|
78
90
|
*/
|
|
79
91
|
export function fromRpcCapabilities(
|
|
80
92
|
capabilities:
|
|
81
|
-
|
|
|
82
|
-
|
|
|
93
|
+
| DecodedPrepareCallsCaps
|
|
94
|
+
| DecodedSendPreparedCallsCaps
|
|
83
95
|
| undefined,
|
|
84
96
|
): PrepareCallsCapabilities | SendPreparedCallsCapabilities | undefined {
|
|
85
97
|
if (!capabilities) return undefined;
|
package/src/utils/schema.ts
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
TObject,
|
|
3
|
+
TSchema,
|
|
4
|
+
TTuple,
|
|
5
|
+
StaticDecode,
|
|
6
|
+
StaticEncode,
|
|
7
|
+
} from "typebox";
|
|
8
|
+
import { Value, EncodeError, DecodeError, Pointer } from "typebox/value";
|
|
9
|
+
import { BaseError } from "@alchemy/common";
|
|
2
10
|
|
|
3
11
|
/** Constraint for RPC method schemas from `@alchemy/wallet-api-types/rpc`. */
|
|
4
12
|
type RpcMethodSchema = TObject<{
|
|
@@ -30,3 +38,73 @@ export type MethodParams<T extends RpcMethodSchema> = StaticDecode<
|
|
|
30
38
|
export type MethodResponse<T extends RpcMethodSchema> = StaticDecode<
|
|
31
39
|
T["properties"]["ReturnType"]
|
|
32
40
|
>;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Formats an {@link EncodeError} or {@link DecodeError} into a human-readable
|
|
44
|
+
* string describing what went wrong, including the JSON path and the schema's
|
|
45
|
+
* custom error message (if any).
|
|
46
|
+
*
|
|
47
|
+
* @param {TSchema} schema - The TypeBox schema that validation was run against.
|
|
48
|
+
* @param {EncodeError | DecodeError} error - The error thrown by {@link Value.Encode} or {@link Value.Decode}.
|
|
49
|
+
* @returns {string} A formatted error string prefixed with `"Invalid params"`.
|
|
50
|
+
*/
|
|
51
|
+
function formatCodecError(
|
|
52
|
+
schema: TSchema,
|
|
53
|
+
error: EncodeError | DecodeError,
|
|
54
|
+
): string {
|
|
55
|
+
// Use only the first error — it's the most specific. Subsequent errors are
|
|
56
|
+
// typically cascade noise from union/anyOf branches.
|
|
57
|
+
const causeError = error.cause.errors[0];
|
|
58
|
+
// errors is typed as an open array — guard against the (practically
|
|
59
|
+
// impossible) empty case.
|
|
60
|
+
if (!causeError) return "Invalid params";
|
|
61
|
+
|
|
62
|
+
const path = causeError.instancePath || "(root)";
|
|
63
|
+
|
|
64
|
+
// Prefer the schema's custom errorMessage annotation over the generic locale message.
|
|
65
|
+
let message = causeError.message;
|
|
66
|
+
const schemaPointer = causeError.schemaPath.replace(/^#/, "");
|
|
67
|
+
if (schemaPointer) {
|
|
68
|
+
const schemaNode = Pointer.Get(schema, schemaPointer);
|
|
69
|
+
if (
|
|
70
|
+
schemaNode &&
|
|
71
|
+
typeof schemaNode === "object" &&
|
|
72
|
+
"errorMessage" in schemaNode &&
|
|
73
|
+
typeof (schemaNode as Record<string, unknown>).errorMessage === "string"
|
|
74
|
+
) {
|
|
75
|
+
message = (schemaNode as Record<string, unknown>).errorMessage as string;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return `Invalid params: ${path}: ${message}`;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Type-safe wrapper around `Value.Encode` with human-readable errors.
|
|
83
|
+
export function encode<const T extends TSchema>(
|
|
84
|
+
schema: T,
|
|
85
|
+
value: StaticDecode<T>,
|
|
86
|
+
): StaticEncode<T> {
|
|
87
|
+
try {
|
|
88
|
+
return Value.Encode(schema, value);
|
|
89
|
+
} catch (error) {
|
|
90
|
+
if (error instanceof EncodeError) {
|
|
91
|
+
throw new BaseError(formatCodecError(schema, error), { cause: error });
|
|
92
|
+
}
|
|
93
|
+
throw error;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Type-safe wrapper around `Value.Decode` with human-readable errors.
|
|
98
|
+
export function decode<const T extends TSchema>(
|
|
99
|
+
schema: T,
|
|
100
|
+
value: StaticEncode<T>,
|
|
101
|
+
): StaticDecode<T> {
|
|
102
|
+
try {
|
|
103
|
+
return Value.Decode(schema, value);
|
|
104
|
+
} catch (error) {
|
|
105
|
+
if (error instanceof DecodeError) {
|
|
106
|
+
throw new BaseError(formatCodecError(schema, error), { cause: error });
|
|
107
|
+
}
|
|
108
|
+
throw error;
|
|
109
|
+
}
|
|
110
|
+
}
|
package/src/version.ts
CHANGED