@atxp/common 0.7.4 → 0.8.1
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/atxpAccount.d.ts +18 -0
- package/dist/atxpAccount.d.ts.map +1 -0
- package/dist/atxpAccount.js +156 -0
- package/dist/atxpAccount.js.map +1 -0
- package/dist/es256kJwtHelper.d.ts +41 -0
- package/dist/es256kJwtHelper.d.ts.map +1 -0
- package/dist/es256kJwtHelper.js +135 -0
- package/dist/es256kJwtHelper.js.map +1 -0
- package/dist/index.cjs +359 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +157 -15
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +354 -7
- package/dist/index.js.map +1 -1
- package/dist/jwt.d.ts +5 -2
- package/dist/jwt.d.ts.map +1 -1
- package/dist/jwt.js +6 -2
- package/dist/jwt.js.map +1 -1
- package/dist/types.d.ts +88 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +57 -1
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,16 +1,8 @@
|
|
|
1
1
|
import * as oauth from 'oauth4webapi';
|
|
2
2
|
import { McpError, JSONRPCMessage } from '@modelcontextprotocol/sdk/types.js';
|
|
3
3
|
|
|
4
|
-
/**
|
|
5
|
-
* Generate a JWT using the jose library and EdDSA (Ed25519) private key.
|
|
6
|
-
* @param walletId - The subject (public key, wallet address, etc.)
|
|
7
|
-
* @param privateKey - Ed25519 private key as a CryptoKey or Uint8Array
|
|
8
|
-
* @param paymentIds - Optional array of payment IDs to include in the payload
|
|
9
|
-
* @returns JWT string
|
|
10
|
-
*/
|
|
11
|
-
declare const generateJWT: (walletId: string, privateKey: CryptoKey | Uint8Array, paymentRequestId: string, codeChallenge: string) => Promise<string>;
|
|
12
|
-
|
|
13
4
|
declare const DEFAULT_AUTHORIZATION_SERVER = "https://auth.atxp.ai";
|
|
5
|
+
declare const DEFAULT_ATXP_ACCOUNTS_SERVER = "https://accounts.atxp.ai";
|
|
14
6
|
declare enum LogLevel {
|
|
15
7
|
DEBUG = 0,
|
|
16
8
|
INFO = 1,
|
|
@@ -25,21 +17,63 @@ type Logger = {
|
|
|
25
17
|
};
|
|
26
18
|
type UrlString = `http://${string}` | `https://${string}`;
|
|
27
19
|
type AuthorizationServerUrl = UrlString;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
20
|
+
declare enum CurrencyEnum {
|
|
21
|
+
USDC = "USDC"
|
|
22
|
+
}
|
|
23
|
+
type Currency = `${CurrencyEnum}`;
|
|
24
|
+
declare enum NetworkEnum {
|
|
25
|
+
Solana = "solana",
|
|
26
|
+
Base = "base",
|
|
27
|
+
World = "world",
|
|
28
|
+
Polygon = "polygon",
|
|
29
|
+
BaseSepolia = "base_sepolia",
|
|
30
|
+
WorldSepolia = "world_sepolia",
|
|
31
|
+
PolygonAmoy = "polygon_amoy",
|
|
32
|
+
ATXP = "atxp"
|
|
33
|
+
}
|
|
34
|
+
type Network = `${NetworkEnum}`;
|
|
35
|
+
declare enum ChainEnum {
|
|
36
|
+
Solana = "solana",
|
|
37
|
+
Base = "base",
|
|
38
|
+
World = "world",
|
|
39
|
+
Polygon = "polygon",
|
|
40
|
+
BaseSepolia = "base_sepolia",
|
|
41
|
+
WorldSepolia = "world_sepolia",
|
|
42
|
+
PolygonAmoy = "polygon_amoy"
|
|
43
|
+
}
|
|
44
|
+
type Chain = `${ChainEnum}`;
|
|
45
|
+
declare enum WalletTypeEnum {
|
|
46
|
+
EOA = "eoa",
|
|
47
|
+
Smart = "smart"
|
|
48
|
+
}
|
|
49
|
+
type WalletType = `${WalletTypeEnum}`;
|
|
50
|
+
type AccountId = `${Network}:${string}`;
|
|
51
|
+
type Source = {
|
|
52
|
+
address: string;
|
|
53
|
+
chain: Chain;
|
|
54
|
+
walletType: WalletType;
|
|
55
|
+
};
|
|
56
|
+
type PaymentRequestOption = {
|
|
31
57
|
network: Network;
|
|
32
58
|
currency: Currency;
|
|
33
59
|
address: string;
|
|
34
60
|
amount: BigNumber;
|
|
35
61
|
};
|
|
62
|
+
type Destination = {
|
|
63
|
+
chain: Chain;
|
|
64
|
+
currency: Currency;
|
|
65
|
+
address: string;
|
|
66
|
+
amount: BigNumber;
|
|
67
|
+
};
|
|
36
68
|
type PaymentRequestData = {
|
|
37
|
-
destinations?:
|
|
69
|
+
destinations?: PaymentRequestOption[];
|
|
38
70
|
amount?: BigNumber;
|
|
39
71
|
currency?: Currency;
|
|
40
72
|
network?: Network;
|
|
41
73
|
destination?: string;
|
|
42
74
|
source: string;
|
|
75
|
+
sourceAccountId?: AccountId | null;
|
|
76
|
+
destinationAccountId?: AccountId | null;
|
|
43
77
|
resource: URL;
|
|
44
78
|
resourceName: string;
|
|
45
79
|
payeeName?: string | null;
|
|
@@ -48,6 +82,7 @@ type PaymentRequestData = {
|
|
|
48
82
|
type CustomJWTPayload = {
|
|
49
83
|
code_challenge?: string;
|
|
50
84
|
payment_request_id?: string;
|
|
85
|
+
account_id?: AccountId;
|
|
51
86
|
};
|
|
52
87
|
type ClientCredentials = {
|
|
53
88
|
clientId: string;
|
|
@@ -88,6 +123,57 @@ type RequirePaymentConfig = {
|
|
|
88
123
|
price: BigNumber;
|
|
89
124
|
getExistingPaymentId?: () => Promise<string | null>;
|
|
90
125
|
};
|
|
126
|
+
type PaymentIdentifier = {
|
|
127
|
+
transactionId: string;
|
|
128
|
+
transactionSubId?: string;
|
|
129
|
+
chain: Chain;
|
|
130
|
+
currency: Currency;
|
|
131
|
+
};
|
|
132
|
+
interface PaymentMaker {
|
|
133
|
+
makePayment: (destinations: Destination[], memo: string, paymentRequestId?: string) => Promise<PaymentIdentifier | null>;
|
|
134
|
+
generateJWT: (params: {
|
|
135
|
+
paymentRequestId: string;
|
|
136
|
+
codeChallenge: string;
|
|
137
|
+
accountId?: AccountId | null;
|
|
138
|
+
}) => Promise<string>;
|
|
139
|
+
getSourceAddress: (params: {
|
|
140
|
+
amount: BigNumber;
|
|
141
|
+
currency: Currency;
|
|
142
|
+
receiver: string;
|
|
143
|
+
memo: string;
|
|
144
|
+
}) => string | Promise<string>;
|
|
145
|
+
}
|
|
146
|
+
interface DestinationMaker {
|
|
147
|
+
makeDestinations: (option: PaymentRequestOption, logger: Logger, paymentRequestId: string, sources: Source[]) => Promise<Destination[]>;
|
|
148
|
+
}
|
|
149
|
+
type Account = {
|
|
150
|
+
accountId: AccountId;
|
|
151
|
+
paymentMakers: PaymentMaker[];
|
|
152
|
+
getSources: () => Promise<Source[]>;
|
|
153
|
+
};
|
|
154
|
+
/**
|
|
155
|
+
* Extract the address portion from a fully-qualified accountId
|
|
156
|
+
* @param accountId - Format: network:address
|
|
157
|
+
* @returns The address portion
|
|
158
|
+
*/
|
|
159
|
+
declare function extractAddressFromAccountId(accountId: AccountId): string;
|
|
160
|
+
/**
|
|
161
|
+
* Extract the network portion from a fully-qualified accountId
|
|
162
|
+
* @param accountId - Format: network:address
|
|
163
|
+
* @returns The network portion
|
|
164
|
+
*/
|
|
165
|
+
declare function extractNetworkFromAccountId(accountId: AccountId): Network;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Generate a JWT using the jose library and EdDSA (Ed25519) private key.
|
|
169
|
+
* @param walletId - The subject (public key, wallet address, etc.)
|
|
170
|
+
* @param privateKey - Ed25519 private key as a CryptoKey or Uint8Array
|
|
171
|
+
* @param paymentRequestId - Optional payment request ID to include in the payload
|
|
172
|
+
* @param codeChallenge - Optional code challenge for PKCE
|
|
173
|
+
* @param accountId - Optional account ID to include in the payload
|
|
174
|
+
* @returns JWT string
|
|
175
|
+
*/
|
|
176
|
+
declare const generateJWT: (walletId: string, privateKey: CryptoKey | Uint8Array, paymentRequestId: string, codeChallenge: string, accountId?: AccountId) => Promise<string>;
|
|
91
177
|
|
|
92
178
|
declare class ConsoleLogger implements Logger {
|
|
93
179
|
private readonly prefix;
|
|
@@ -293,6 +379,46 @@ declare function constructEIP1271Message({ walletAddress, timestamp, nonce, code
|
|
|
293
379
|
paymentRequestId?: string;
|
|
294
380
|
}): string;
|
|
295
381
|
|
|
382
|
+
interface ES256KJWTPayload {
|
|
383
|
+
sub: string;
|
|
384
|
+
iss: string;
|
|
385
|
+
aud: string;
|
|
386
|
+
iat: number;
|
|
387
|
+
exp: number;
|
|
388
|
+
code_challenge?: string;
|
|
389
|
+
payment_request_id?: string;
|
|
390
|
+
account_id?: AccountId;
|
|
391
|
+
source_address?: string;
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Build the unsigned JWT message that needs to be signed
|
|
395
|
+
*
|
|
396
|
+
* @param params Parameters for building the JWT message
|
|
397
|
+
* @returns Object containing the message to sign and the encoded header/payload
|
|
398
|
+
*/
|
|
399
|
+
declare function buildES256KJWTMessage(params: {
|
|
400
|
+
walletAddress: string;
|
|
401
|
+
codeChallenge: string;
|
|
402
|
+
paymentRequestId: string;
|
|
403
|
+
accountId?: AccountId | null;
|
|
404
|
+
}): {
|
|
405
|
+
message: string;
|
|
406
|
+
headerB64: string;
|
|
407
|
+
payloadB64: string;
|
|
408
|
+
};
|
|
409
|
+
/**
|
|
410
|
+
* Complete an ES256K JWT with a signature
|
|
411
|
+
*
|
|
412
|
+
* @param params Parameters for completing the JWT
|
|
413
|
+
* @param params.message The message that was signed (header.payload)
|
|
414
|
+
* @param params.signature The ECDSA signature from personal_sign (0x... 130 hex chars / 65 bytes)
|
|
415
|
+
* @returns Complete ES256K JWT string
|
|
416
|
+
*/
|
|
417
|
+
declare function completeES256KJWT(params: {
|
|
418
|
+
message: string;
|
|
419
|
+
signature: string;
|
|
420
|
+
}): string;
|
|
421
|
+
|
|
296
422
|
/**
|
|
297
423
|
* Cache interface for abstracting cache mechanisms
|
|
298
424
|
* This allows for easy mocking in tests and potential future
|
|
@@ -333,5 +459,21 @@ declare class MemoryCache implements ICache<string> {
|
|
|
333
459
|
clear(): void;
|
|
334
460
|
}
|
|
335
461
|
|
|
336
|
-
|
|
337
|
-
|
|
462
|
+
declare class ATXPAccount implements Account {
|
|
463
|
+
accountId: AccountId;
|
|
464
|
+
paymentMakers: PaymentMaker[];
|
|
465
|
+
origin: string;
|
|
466
|
+
token: string;
|
|
467
|
+
fetchFn: FetchLike;
|
|
468
|
+
private unqualifiedAccountId;
|
|
469
|
+
constructor(connectionString: string, opts?: {
|
|
470
|
+
fetchFn?: FetchLike;
|
|
471
|
+
});
|
|
472
|
+
/**
|
|
473
|
+
* Get sources for this account by calling the accounts service
|
|
474
|
+
*/
|
|
475
|
+
getSources(): Promise<Source[]>;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
export { ATXPAccount, BrowserCache, ChainEnum, ConsoleLogger, CurrencyEnum, DEFAULT_ATXP_ACCOUNTS_SERVER, DEFAULT_AUTHORIZATION_SERVER, JsonCache, LogLevel, MemoryCache, MemoryOAuthDb, NetworkEnum, OAuthResourceClient, PAYMENT_REQUIRED_ERROR_CODE, PAYMENT_REQUIRED_PREAMBLE, Servers, WalletTypeEnum, assertNever, buildES256KJWTMessage, completeES256KJWT, constructEIP1271Message, createEIP1271AuthData, createEIP1271JWT, createLegacyEIP1271Auth, createReactNativeSafeFetch, crypto, extractAddressFromAccountId, extractJSONFromSSE, extractNetworkFromAccountId, generateJWT, getIsReactNative, isBrowser, isEnumValue, isNextJS, isNode, isSSEResponse, isWebEnvironment, parseMcpMessages, parsePaymentRequests, parseSSEMessages, paymentRequiredError };
|
|
479
|
+
export type { AccessToken, Account, AccountId, AuthorizationServerUrl, Chain, ClientCredentials, Currency, CustomJWTPayload, Destination, DestinationMaker, ES256KJWTPayload, FetchLike, ICache, Logger, MemoryOAuthDbConfig, Network, OAuthDb, OAuthResourceClientConfig, OAuthResourceDb, PKCEValues, PaymentIdentifier, PaymentMaker, PaymentRequestData, PaymentRequestOption, PlatformCrypto, RequirePaymentConfig, SSEMessage, Source, TokenData, UrlString, WalletType };
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAGvC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG5C,OAAO,EACL,aAAa,EACb,KAAK,mBAAmB,EACzB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,mBAAmB,EACnB,KAAK,yBAAyB,EAC/B,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,2BAA2B,EAC3B,yBAAyB,EACzB,oBAAoB,EACrB,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,OAAO,EACL,4BAA4B,EAC5B,QAAQ,EACR,KAAK,MAAM,EACX,KAAK,SAAS,EACd,KAAK,sBAAsB,EAC3B,KAAK,QAAQ,EACb,KAAK,OAAO,EACZ,KAAK,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAGvC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG5C,OAAO,EACL,aAAa,EACb,KAAK,mBAAmB,EACzB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,mBAAmB,EACnB,KAAK,yBAAyB,EAC/B,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,2BAA2B,EAC3B,yBAAyB,EACzB,oBAAoB,EACrB,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,OAAO,EACL,4BAA4B,EAC5B,4BAA4B,EAC5B,QAAQ,EACR,KAAK,MAAM,EACX,KAAK,SAAS,EACd,KAAK,sBAAsB,EAC3B,YAAY,EACZ,KAAK,QAAQ,EACb,WAAW,EACX,KAAK,OAAO,EACZ,SAAS,EACT,KAAK,KAAK,EACV,cAAc,EACd,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,oBAAoB,EACzB,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,OAAO,EACZ,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,OAAO,EACZ,KAAK,MAAM,EACX,2BAA2B,EAC3B,2BAA2B,EAC5B,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,WAAW,EACX,WAAW,EACZ,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EACjB,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,KAAK,UAAU,EACf,gBAAgB,EAChB,kBAAkB,EAClB,aAAa,EACd,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,KAAK,cAAc,EACnB,gBAAgB,EAChB,MAAM,EACN,SAAS,EACT,QAAQ,EACR,gBAAgB,EAChB,0BAA0B,EAC1B,MAAM,EACP,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,qBAAqB,EACrB,uBAAuB,EACxB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,KAAK,gBAAgB,EACtB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EACL,KAAK,MAAM,EACX,SAAS,EACT,YAAY,EACZ,WAAW,EACZ,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,WAAW,EACZ,MAAM,kBAAkB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -4,16 +4,18 @@ import { McpError, isJSONRPCError, isJSONRPCResponse, JSONRPCMessageSchema } fro
|
|
|
4
4
|
import { ZodError } from 'zod';
|
|
5
5
|
|
|
6
6
|
// TODO: revisit this
|
|
7
|
-
const ISSUER = 'atxp.ai';
|
|
8
|
-
const AUDIENCE = 'https://auth.atxp.ai';
|
|
7
|
+
const ISSUER$1 = 'atxp.ai';
|
|
8
|
+
const AUDIENCE$1 = 'https://auth.atxp.ai';
|
|
9
9
|
/**
|
|
10
10
|
* Generate a JWT using the jose library and EdDSA (Ed25519) private key.
|
|
11
11
|
* @param walletId - The subject (public key, wallet address, etc.)
|
|
12
12
|
* @param privateKey - Ed25519 private key as a CryptoKey or Uint8Array
|
|
13
|
-
* @param
|
|
13
|
+
* @param paymentRequestId - Optional payment request ID to include in the payload
|
|
14
|
+
* @param codeChallenge - Optional code challenge for PKCE
|
|
15
|
+
* @param accountId - Optional account ID to include in the payload
|
|
14
16
|
* @returns JWT string
|
|
15
17
|
*/
|
|
16
|
-
const generateJWT = async (walletId, privateKey, paymentRequestId, codeChallenge) => {
|
|
18
|
+
const generateJWT = async (walletId, privateKey, paymentRequestId, codeChallenge, accountId) => {
|
|
17
19
|
const payload = {
|
|
18
20
|
code_challenge: codeChallenge,
|
|
19
21
|
};
|
|
@@ -21,11 +23,13 @@ const generateJWT = async (walletId, privateKey, paymentRequestId, codeChallenge
|
|
|
21
23
|
payload.payment_request_id = paymentRequestId;
|
|
22
24
|
if (codeChallenge)
|
|
23
25
|
payload.code_challenge = codeChallenge;
|
|
26
|
+
if (accountId)
|
|
27
|
+
payload.account_id = accountId;
|
|
24
28
|
return await new SignJWT(payload)
|
|
25
29
|
.setProtectedHeader({ alg: 'EdDSA', typ: 'JWT' })
|
|
26
30
|
.setIssuedAt()
|
|
27
|
-
.setIssuer(ISSUER)
|
|
28
|
-
.setAudience(AUDIENCE)
|
|
31
|
+
.setIssuer(ISSUER$1)
|
|
32
|
+
.setAudience(AUDIENCE$1)
|
|
29
33
|
.setSubject(walletId)
|
|
30
34
|
.setExpirationTime('2m')
|
|
31
35
|
.sign(privateKey);
|
|
@@ -56,6 +60,7 @@ function isEnumValue(enumObj, value) {
|
|
|
56
60
|
}
|
|
57
61
|
|
|
58
62
|
const DEFAULT_AUTHORIZATION_SERVER = 'https://auth.atxp.ai';
|
|
63
|
+
const DEFAULT_ATXP_ACCOUNTS_SERVER = 'https://accounts.atxp.ai';
|
|
59
64
|
var LogLevel;
|
|
60
65
|
(function (LogLevel) {
|
|
61
66
|
LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
|
|
@@ -63,6 +68,61 @@ var LogLevel;
|
|
|
63
68
|
LogLevel[LogLevel["WARN"] = 2] = "WARN";
|
|
64
69
|
LogLevel[LogLevel["ERROR"] = 3] = "ERROR";
|
|
65
70
|
})(LogLevel || (LogLevel = {}));
|
|
71
|
+
// Enums provide runtime access to valid values
|
|
72
|
+
var CurrencyEnum;
|
|
73
|
+
(function (CurrencyEnum) {
|
|
74
|
+
CurrencyEnum["USDC"] = "USDC";
|
|
75
|
+
})(CurrencyEnum || (CurrencyEnum = {}));
|
|
76
|
+
var NetworkEnum;
|
|
77
|
+
(function (NetworkEnum) {
|
|
78
|
+
NetworkEnum["Solana"] = "solana";
|
|
79
|
+
NetworkEnum["Base"] = "base";
|
|
80
|
+
NetworkEnum["World"] = "world";
|
|
81
|
+
NetworkEnum["Polygon"] = "polygon";
|
|
82
|
+
NetworkEnum["BaseSepolia"] = "base_sepolia";
|
|
83
|
+
NetworkEnum["WorldSepolia"] = "world_sepolia";
|
|
84
|
+
NetworkEnum["PolygonAmoy"] = "polygon_amoy";
|
|
85
|
+
NetworkEnum["ATXP"] = "atxp";
|
|
86
|
+
})(NetworkEnum || (NetworkEnum = {}));
|
|
87
|
+
var ChainEnum;
|
|
88
|
+
(function (ChainEnum) {
|
|
89
|
+
ChainEnum["Solana"] = "solana";
|
|
90
|
+
ChainEnum["Base"] = "base";
|
|
91
|
+
ChainEnum["World"] = "world";
|
|
92
|
+
ChainEnum["Polygon"] = "polygon";
|
|
93
|
+
ChainEnum["BaseSepolia"] = "base_sepolia";
|
|
94
|
+
ChainEnum["WorldSepolia"] = "world_sepolia";
|
|
95
|
+
ChainEnum["PolygonAmoy"] = "polygon_amoy";
|
|
96
|
+
})(ChainEnum || (ChainEnum = {}));
|
|
97
|
+
var WalletTypeEnum;
|
|
98
|
+
(function (WalletTypeEnum) {
|
|
99
|
+
WalletTypeEnum["EOA"] = "eoa";
|
|
100
|
+
WalletTypeEnum["Smart"] = "smart";
|
|
101
|
+
})(WalletTypeEnum || (WalletTypeEnum = {}));
|
|
102
|
+
/**
|
|
103
|
+
* Extract the address portion from a fully-qualified accountId
|
|
104
|
+
* @param accountId - Format: network:address
|
|
105
|
+
* @returns The address portion
|
|
106
|
+
*/
|
|
107
|
+
function extractAddressFromAccountId(accountId) {
|
|
108
|
+
const parts = accountId.split(':');
|
|
109
|
+
if (parts.length !== 2) {
|
|
110
|
+
throw new Error(`Invalid accountId format: ${accountId}. Expected format: network:address`);
|
|
111
|
+
}
|
|
112
|
+
return parts[1];
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Extract the network portion from a fully-qualified accountId
|
|
116
|
+
* @param accountId - Format: network:address
|
|
117
|
+
* @returns The network portion
|
|
118
|
+
*/
|
|
119
|
+
function extractNetworkFromAccountId(accountId) {
|
|
120
|
+
const parts = accountId.split(':');
|
|
121
|
+
if (parts.length !== 2) {
|
|
122
|
+
throw new Error(`Invalid accountId format: ${accountId}. Expected format: network:address`);
|
|
123
|
+
}
|
|
124
|
+
return parts[0];
|
|
125
|
+
}
|
|
66
126
|
|
|
67
127
|
/* eslint-disable no-console */
|
|
68
128
|
class ConsoleLogger {
|
|
@@ -990,6 +1050,139 @@ function constructEIP1271Message({ walletAddress, timestamp, nonce, codeChalleng
|
|
|
990
1050
|
return messageParts.join('\n');
|
|
991
1051
|
}
|
|
992
1052
|
|
|
1053
|
+
/**
|
|
1054
|
+
* ES256K JWT Helper for Browser Wallets
|
|
1055
|
+
*
|
|
1056
|
+
* This module provides functions to create ES256K JWTs for Ethereum EOA (Externally Owned Account)
|
|
1057
|
+
* wallets in browser environments. Unlike EIP-1271 which is designed for smart contract wallets,
|
|
1058
|
+
* ES256K works with standard ECDSA signatures from wallets like MetaMask.
|
|
1059
|
+
*
|
|
1060
|
+
* The auth server verifies these JWTs using cryptographic signature recovery, which:
|
|
1061
|
+
* - Works with standard 65-byte ECDSA signatures (r, s, v)
|
|
1062
|
+
* - Doesn't require smart contract calls
|
|
1063
|
+
* - Is faster and more efficient for EOA wallets
|
|
1064
|
+
*/
|
|
1065
|
+
const ISSUER = 'atxp.ai';
|
|
1066
|
+
const AUDIENCE = 'https://auth.atxp.ai';
|
|
1067
|
+
/**
|
|
1068
|
+
* Build the unsigned JWT message that needs to be signed
|
|
1069
|
+
*
|
|
1070
|
+
* @param params Parameters for building the JWT message
|
|
1071
|
+
* @returns Object containing the message to sign and the encoded header/payload
|
|
1072
|
+
*/
|
|
1073
|
+
function buildES256KJWTMessage(params) {
|
|
1074
|
+
const now = Math.floor(Date.now() / 1000);
|
|
1075
|
+
// Build the payload
|
|
1076
|
+
const payload = {
|
|
1077
|
+
sub: params.accountId || params.walletAddress,
|
|
1078
|
+
iss: ISSUER,
|
|
1079
|
+
aud: AUDIENCE,
|
|
1080
|
+
iat: now,
|
|
1081
|
+
exp: now + 120, // 2 minutes expiration
|
|
1082
|
+
};
|
|
1083
|
+
// Add optional fields only if they have values
|
|
1084
|
+
if (params.codeChallenge) {
|
|
1085
|
+
payload.code_challenge = params.codeChallenge;
|
|
1086
|
+
}
|
|
1087
|
+
if (params.paymentRequestId) {
|
|
1088
|
+
payload.payment_request_id = params.paymentRequestId;
|
|
1089
|
+
}
|
|
1090
|
+
if (params.accountId) {
|
|
1091
|
+
payload.account_id = params.accountId;
|
|
1092
|
+
payload.source_address = params.walletAddress;
|
|
1093
|
+
}
|
|
1094
|
+
// Create JWT header
|
|
1095
|
+
const header = {
|
|
1096
|
+
alg: 'ES256K',
|
|
1097
|
+
typ: 'JWT'
|
|
1098
|
+
};
|
|
1099
|
+
// Encode header and payload as base64url
|
|
1100
|
+
const headerB64 = base64urlEncode(JSON.stringify(header));
|
|
1101
|
+
const payloadB64 = base64urlEncode(JSON.stringify(payload));
|
|
1102
|
+
// The message to sign is header.payload
|
|
1103
|
+
const message = `${headerB64}.${payloadB64}`;
|
|
1104
|
+
return { message, headerB64, payloadB64 };
|
|
1105
|
+
}
|
|
1106
|
+
/**
|
|
1107
|
+
* Complete an ES256K JWT with a signature
|
|
1108
|
+
*
|
|
1109
|
+
* @param params Parameters for completing the JWT
|
|
1110
|
+
* @param params.message The message that was signed (header.payload)
|
|
1111
|
+
* @param params.signature The ECDSA signature from personal_sign (0x... 130 hex chars / 65 bytes)
|
|
1112
|
+
* @returns Complete ES256K JWT string
|
|
1113
|
+
*/
|
|
1114
|
+
function completeES256KJWT(params) {
|
|
1115
|
+
// Convert the signature from hex to base64url
|
|
1116
|
+
// The signature from personal_sign is in format: 0x + r (32 bytes) + s (32 bytes) + v (1 byte)
|
|
1117
|
+
// For JWT ES256K, we need just r + s in base64url format (v is implicit)
|
|
1118
|
+
let signature = params.signature;
|
|
1119
|
+
if (signature.startsWith('0x')) {
|
|
1120
|
+
signature = signature.slice(2);
|
|
1121
|
+
}
|
|
1122
|
+
// Validate signature length (should be 130 hex chars = 65 bytes)
|
|
1123
|
+
if (signature.length !== 130) {
|
|
1124
|
+
throw new Error(`Invalid signature length: expected 130 hex chars, got ${signature.length}`);
|
|
1125
|
+
}
|
|
1126
|
+
// Extract r and s (first 64 bytes, ignore v which is the last byte)
|
|
1127
|
+
const rHex = signature.slice(0, 64);
|
|
1128
|
+
const sHex = signature.slice(64, 128);
|
|
1129
|
+
const vHex = signature.slice(128, 130);
|
|
1130
|
+
// Convert r and s to bytes
|
|
1131
|
+
const rBytes = hexToBytes(rHex);
|
|
1132
|
+
const sBytes = hexToBytes(sHex);
|
|
1133
|
+
const vByte = parseInt(vHex, 16);
|
|
1134
|
+
// Normalize v to 0 or 1 (MetaMask returns 27/28, but we need 0/1)
|
|
1135
|
+
const vNormalized = vByte >= 27 ? vByte - 27 : vByte;
|
|
1136
|
+
// Combine r + s + v as a single byte array
|
|
1137
|
+
const signatureBytes = new Uint8Array(65);
|
|
1138
|
+
signatureBytes.set(rBytes, 0);
|
|
1139
|
+
signatureBytes.set(sBytes, 32);
|
|
1140
|
+
signatureBytes[64] = vNormalized;
|
|
1141
|
+
// Encode as base64url
|
|
1142
|
+
const signatureB64 = base64urlEncodeBytes(signatureBytes);
|
|
1143
|
+
// Construct the JWT
|
|
1144
|
+
return `${params.message}.${signatureB64}`;
|
|
1145
|
+
}
|
|
1146
|
+
/**
|
|
1147
|
+
* Base64URL encode a string
|
|
1148
|
+
*/
|
|
1149
|
+
function base64urlEncode(str) {
|
|
1150
|
+
// Convert string to bytes
|
|
1151
|
+
const bytes = new TextEncoder().encode(str);
|
|
1152
|
+
return base64urlEncodeBytes(bytes);
|
|
1153
|
+
}
|
|
1154
|
+
/**
|
|
1155
|
+
* Base64URL encode a byte array
|
|
1156
|
+
*/
|
|
1157
|
+
function base64urlEncodeBytes(bytes) {
|
|
1158
|
+
// Convert to base64
|
|
1159
|
+
let base64 = '';
|
|
1160
|
+
if (typeof Buffer !== 'undefined') {
|
|
1161
|
+
// Node.js environment
|
|
1162
|
+
base64 = Buffer.from(bytes).toString('base64');
|
|
1163
|
+
}
|
|
1164
|
+
else {
|
|
1165
|
+
// Browser environment
|
|
1166
|
+
const binary = Array.from(bytes).map(b => String.fromCharCode(b)).join('');
|
|
1167
|
+
base64 = btoa(binary);
|
|
1168
|
+
}
|
|
1169
|
+
// Convert base64 to base64url (replace +/= with -_)
|
|
1170
|
+
return base64
|
|
1171
|
+
.replace(/\+/g, '-')
|
|
1172
|
+
.replace(/\//g, '_')
|
|
1173
|
+
.replace(/=/g, '');
|
|
1174
|
+
}
|
|
1175
|
+
/**
|
|
1176
|
+
* Convert hex string to bytes
|
|
1177
|
+
*/
|
|
1178
|
+
function hexToBytes(hex) {
|
|
1179
|
+
const bytes = new Uint8Array(hex.length / 2);
|
|
1180
|
+
for (let i = 0; i < hex.length; i += 2) {
|
|
1181
|
+
bytes[i / 2] = parseInt(hex.slice(i, i + 2), 16);
|
|
1182
|
+
}
|
|
1183
|
+
return bytes;
|
|
1184
|
+
}
|
|
1185
|
+
|
|
993
1186
|
/**
|
|
994
1187
|
* Type-safe cache wrapper for JSON data
|
|
995
1188
|
*/
|
|
@@ -1060,5 +1253,159 @@ class MemoryCache {
|
|
|
1060
1253
|
}
|
|
1061
1254
|
}
|
|
1062
1255
|
|
|
1063
|
-
|
|
1256
|
+
function toBasicAuth(token) {
|
|
1257
|
+
// Basic auth is base64("username:password"), password is blank
|
|
1258
|
+
const b64 = Buffer.from(`${token}:`).toString('base64');
|
|
1259
|
+
return `Basic ${b64}`;
|
|
1260
|
+
}
|
|
1261
|
+
function parseConnectionString(connectionString) {
|
|
1262
|
+
const url = new URL(connectionString);
|
|
1263
|
+
const origin = url.origin;
|
|
1264
|
+
const token = url.searchParams.get('connection_token') || '';
|
|
1265
|
+
const accountId = url.searchParams.get('account_id');
|
|
1266
|
+
if (!token) {
|
|
1267
|
+
throw new Error('ATXPAccount: connection string missing connection token');
|
|
1268
|
+
}
|
|
1269
|
+
if (!accountId) {
|
|
1270
|
+
throw new Error('ATXPAccount: connection string missing account id');
|
|
1271
|
+
}
|
|
1272
|
+
return { origin, token, accountId };
|
|
1273
|
+
}
|
|
1274
|
+
class ATXPHttpPaymentMaker {
|
|
1275
|
+
constructor(origin, token, fetchFn = fetch) {
|
|
1276
|
+
this.origin = origin;
|
|
1277
|
+
this.token = token;
|
|
1278
|
+
this.fetchFn = fetchFn;
|
|
1279
|
+
}
|
|
1280
|
+
async getSourceAddress(params) {
|
|
1281
|
+
// Call the /address_for_payment endpoint to get the source address for this account
|
|
1282
|
+
const response = await this.fetchFn(`${this.origin}/address_for_payment`, {
|
|
1283
|
+
method: 'POST',
|
|
1284
|
+
headers: {
|
|
1285
|
+
'Authorization': toBasicAuth(this.token),
|
|
1286
|
+
'Content-Type': 'application/json',
|
|
1287
|
+
},
|
|
1288
|
+
body: JSON.stringify({
|
|
1289
|
+
amount: params.amount.toString(),
|
|
1290
|
+
currency: params.currency,
|
|
1291
|
+
receiver: params.receiver,
|
|
1292
|
+
memo: params.memo,
|
|
1293
|
+
}),
|
|
1294
|
+
});
|
|
1295
|
+
if (!response.ok) {
|
|
1296
|
+
const text = await response.text();
|
|
1297
|
+
throw new Error(`ATXPAccount: /address_for_payment failed: ${response.status} ${response.statusText} ${text}`);
|
|
1298
|
+
}
|
|
1299
|
+
const json = await response.json();
|
|
1300
|
+
if (!json?.sourceAddress) {
|
|
1301
|
+
throw new Error('ATXPAccount: /address_for_payment did not return sourceAddress');
|
|
1302
|
+
}
|
|
1303
|
+
return json.sourceAddress;
|
|
1304
|
+
}
|
|
1305
|
+
async makePayment(destinations, memo, paymentRequestId) {
|
|
1306
|
+
// Make a payment via the /pay endpoint with multiple destinations
|
|
1307
|
+
const response = await this.fetchFn(`${this.origin}/pay`, {
|
|
1308
|
+
method: 'POST',
|
|
1309
|
+
headers: {
|
|
1310
|
+
'Authorization': toBasicAuth(this.token),
|
|
1311
|
+
'Content-Type': 'application/json',
|
|
1312
|
+
},
|
|
1313
|
+
body: JSON.stringify({
|
|
1314
|
+
destinations: destinations.map(d => ({
|
|
1315
|
+
chain: d.chain,
|
|
1316
|
+
address: d.address,
|
|
1317
|
+
amount: d.amount.toString(),
|
|
1318
|
+
currency: d.currency
|
|
1319
|
+
})),
|
|
1320
|
+
memo,
|
|
1321
|
+
...(paymentRequestId && { paymentRequestId })
|
|
1322
|
+
}),
|
|
1323
|
+
});
|
|
1324
|
+
if (!response.ok) {
|
|
1325
|
+
const text = await response.text();
|
|
1326
|
+
throw new Error(`ATXPAccount: /pay failed: ${response.status} ${response.statusText} ${text}`);
|
|
1327
|
+
}
|
|
1328
|
+
const json = await response.json();
|
|
1329
|
+
const transactionId = json.transactionId;
|
|
1330
|
+
if (!transactionId) {
|
|
1331
|
+
throw new Error('ATXPAccount: /pay did not return transactionId or txHash');
|
|
1332
|
+
}
|
|
1333
|
+
if (!json?.chain) {
|
|
1334
|
+
throw new Error('ATXPAccount: /pay did not return chain');
|
|
1335
|
+
}
|
|
1336
|
+
if (!json?.currency) {
|
|
1337
|
+
throw new Error('ATXPAccount: /pay did not return currency');
|
|
1338
|
+
}
|
|
1339
|
+
return {
|
|
1340
|
+
transactionId,
|
|
1341
|
+
...(json.transactionSubId ? { transactionSubId: json.transactionSubId } : {}),
|
|
1342
|
+
chain: json.chain,
|
|
1343
|
+
currency: json.currency
|
|
1344
|
+
};
|
|
1345
|
+
}
|
|
1346
|
+
async generateJWT(params) {
|
|
1347
|
+
const response = await this.fetchFn(`${this.origin}/sign`, {
|
|
1348
|
+
method: 'POST',
|
|
1349
|
+
headers: {
|
|
1350
|
+
'Authorization': toBasicAuth(this.token),
|
|
1351
|
+
'Content-Type': 'application/json',
|
|
1352
|
+
},
|
|
1353
|
+
body: JSON.stringify({
|
|
1354
|
+
paymentRequestId: params.paymentRequestId,
|
|
1355
|
+
codeChallenge: params.codeChallenge,
|
|
1356
|
+
...(params.accountId ? { accountId: params.accountId } : {}),
|
|
1357
|
+
}),
|
|
1358
|
+
});
|
|
1359
|
+
if (!response.ok) {
|
|
1360
|
+
const text = await response.text();
|
|
1361
|
+
throw new Error(`ATXPAccount: /sign failed: ${response.status} ${response.statusText} ${text}`);
|
|
1362
|
+
}
|
|
1363
|
+
const json = await response.json();
|
|
1364
|
+
if (!json?.jwt) {
|
|
1365
|
+
throw new Error('ATXPAccount: /sign did not return jwt');
|
|
1366
|
+
}
|
|
1367
|
+
return json.jwt;
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1370
|
+
class ATXPAccount {
|
|
1371
|
+
constructor(connectionString, opts) {
|
|
1372
|
+
const { origin, token, accountId } = parseConnectionString(connectionString);
|
|
1373
|
+
const fetchFn = opts?.fetchFn ?? fetch;
|
|
1374
|
+
// Store for use in X402 payment creation
|
|
1375
|
+
this.origin = origin;
|
|
1376
|
+
this.token = token;
|
|
1377
|
+
this.fetchFn = fetchFn;
|
|
1378
|
+
// Format accountId as network:address
|
|
1379
|
+
// Connection string provides just the atxp_acct_xxx part (no prefix for UI)
|
|
1380
|
+
this.unqualifiedAccountId = accountId;
|
|
1381
|
+
this.accountId = `atxp:${accountId}`;
|
|
1382
|
+
this.paymentMakers = [
|
|
1383
|
+
new ATXPHttpPaymentMaker(origin, token, fetchFn)
|
|
1384
|
+
];
|
|
1385
|
+
}
|
|
1386
|
+
/**
|
|
1387
|
+
* Get sources for this account by calling the accounts service
|
|
1388
|
+
*/
|
|
1389
|
+
async getSources() {
|
|
1390
|
+
// Use the unqualified account ID (without atxp: prefix) for the API call
|
|
1391
|
+
const response = await this.fetchFn(`${this.origin}/account/${this.unqualifiedAccountId}/sources`, {
|
|
1392
|
+
method: 'GET',
|
|
1393
|
+
headers: {
|
|
1394
|
+
'Accept': 'application/json',
|
|
1395
|
+
}
|
|
1396
|
+
});
|
|
1397
|
+
if (!response.ok) {
|
|
1398
|
+
const text = await response.text();
|
|
1399
|
+
throw new Error(`ATXPAccount: /account/${this.unqualifiedAccountId}/sources failed: ${response.status} ${response.statusText} ${text}`);
|
|
1400
|
+
}
|
|
1401
|
+
const json = await response.json();
|
|
1402
|
+
// The accounts service returns the sources array directly, not wrapped in an object
|
|
1403
|
+
if (!Array.isArray(json)) {
|
|
1404
|
+
throw new Error(`ATXPAccount: /account/${this.unqualifiedAccountId}/sources did not return sources array`);
|
|
1405
|
+
}
|
|
1406
|
+
return json;
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
|
|
1410
|
+
export { ATXPAccount, BrowserCache, ChainEnum, ConsoleLogger, CurrencyEnum, DEFAULT_ATXP_ACCOUNTS_SERVER, DEFAULT_AUTHORIZATION_SERVER, JsonCache, LogLevel, MemoryCache, MemoryOAuthDb, NetworkEnum, OAuthResourceClient, PAYMENT_REQUIRED_ERROR_CODE, PAYMENT_REQUIRED_PREAMBLE, Servers, WalletTypeEnum, assertNever, buildES256KJWTMessage, completeES256KJWT, constructEIP1271Message, createEIP1271AuthData, createEIP1271JWT, createLegacyEIP1271Auth, createReactNativeSafeFetch, crypto, extractAddressFromAccountId, extractJSONFromSSE, extractNetworkFromAccountId, generateJWT, getIsReactNative, isBrowser, isEnumValue, isNextJS, isNode, isSSEResponse, isWebEnvironment, parseMcpMessages, parsePaymentRequests, parseSSEMessages, paymentRequiredError };
|
|
1064
1411
|
//# sourceMappingURL=index.js.map
|