@moon-x/node-sdk 0.7.1 → 0.8.0
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/README.md +41 -4
- package/dist/index.d.mts +78 -7
- package/dist/index.d.ts +78 -7
- package/dist/index.js +160 -2
- package/dist/index.mjs +153 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -87,6 +87,38 @@ Returns `Promise<{ access: AccessTokenClaims, identity: IdentityTokenClaims | nu
|
|
|
87
87
|
|
|
88
88
|
Canonical entry point — use this from request handlers. Cross-checks the two tokens' subjects when both are present.
|
|
89
89
|
|
|
90
|
+
### `client.funding.sign(params)`
|
|
91
|
+
|
|
92
|
+
Request a signed MoonPay Buy-widget URL for a user's wallet, so your backend can drive the card-funding flow without holding MoonPay keys. Returns `Promise<MoonPaySignResponse>`.
|
|
93
|
+
|
|
94
|
+
The route is publishable-key acceptable but signs **only** for an address that belongs to the authenticated user, so you forward that user's access token per call:
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
const funding = await moonx.funding.sign({
|
|
98
|
+
accessToken: req.headers["x-moonx-access-token"]!, // the end user's token
|
|
99
|
+
publicAddress: "0xUserWalletAddress",
|
|
100
|
+
useSandbox: true, // omit or false for production
|
|
101
|
+
currencyCode: "eth", // optional MoonPay presets
|
|
102
|
+
quoteCurrencyAmount: 50,
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// funding.signed_url — open this for the user
|
|
106
|
+
// funding.external_transaction_id — correlate the purchase
|
|
107
|
+
// funding.provider_publishable_key — MoonPay pk the URL was signed with
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
| Param | Type | Required | Notes |
|
|
111
|
+
|---|---|---|---|
|
|
112
|
+
| `accessToken` | `string` | Yes | The end user's MoonX access token |
|
|
113
|
+
| `publicAddress` | `string` | Yes | Wallet address to fund; must belong to the user |
|
|
114
|
+
| `useSandbox` | `boolean` | No | `true` → MoonPay sandbox; defaults to `false` |
|
|
115
|
+
| `currencyCode` | `string` | No | MoonPay currency to preselect |
|
|
116
|
+
| `quoteCurrencyAmount` | `number` | No | Pin the fiat amount; omit to let the user choose |
|
|
117
|
+
| `paymentMethod` | `string` | No | MoonPay payment method to preselect |
|
|
118
|
+
| `uiConfig` | `{ theme?, accentColor? }` | No | Widget theming |
|
|
119
|
+
|
|
120
|
+
Failures throw a typed `MoonXError` subclass: `IntegrationNotConfiguredError` (400), `UnauthorizedError` (401), `WalletOwnershipError` (403), `RateLimitedError` (429).
|
|
121
|
+
|
|
90
122
|
## Errors
|
|
91
123
|
|
|
92
124
|
All thrown errors extend `MoonXError`, which carries a `.code` property for programmatic handling:
|
|
@@ -128,11 +160,16 @@ try {
|
|
|
128
160
|
| `UnsupportedAlgorithmError` | `unsupported_algorithm` | Token uses something other than ES256 |
|
|
129
161
|
| `JwksFetchError` | `jwks_fetch_failed` | Couldn't fetch the JWKS from MoonX |
|
|
130
162
|
| `AppResolutionError` | `app_resolution_failed` | Publishable-key → app-id lookup failed |
|
|
131
|
-
| `ConfigurationError` | `configuration_error` | Bad `MoonXClient` config
|
|
163
|
+
| `ConfigurationError` | `configuration_error` | Bad `MoonXClient` config, or a missing required call param |
|
|
164
|
+
| `IntegrationNotConfiguredError` | `integration_not_configured` | MoonPay funding is not configured or is disabled for this app (400) |
|
|
165
|
+
| `WalletOwnershipError` | `wallet_ownership` | The wallet address does not belong to the user (403) |
|
|
166
|
+
| `UnauthorizedError` | `unauthorized` | Missing or invalid credentials (401) |
|
|
167
|
+
| `RateLimitedError` | `rate_limited` | Request was rate limited (429) |
|
|
168
|
+
| `RequestFailedError` | `request_failed` | Unexpected non-2xx response (carries `.status`) |
|
|
132
169
|
|
|
133
170
|
### Type imports
|
|
134
171
|
|
|
135
|
-
`AccessTokenClaims`, `IdentityTokenClaims`, `BaseTokenClaims`, and `
|
|
172
|
+
`AccessTokenClaims`, `IdentityTokenClaims`, `BaseTokenClaims`, `VerifiedSession`, and `MoonPaySignResponse` are also exported from `@moon-x/core/types` — the single source of truth shared with the browser + RN SDKs. Either import path works:
|
|
136
173
|
|
|
137
174
|
```ts
|
|
138
175
|
// From node-sdk (convenience re-export):
|
|
@@ -148,5 +185,5 @@ Auth providers ship server SDKs partly to abstract away `jose`-style JWT librari
|
|
|
148
185
|
|
|
149
186
|
## Roadmap
|
|
150
187
|
|
|
151
|
-
- **Current**: auth (`verifyAccessToken`, `verifyIdentityToken`, `verifySession`)
|
|
152
|
-
- **
|
|
188
|
+
- **Current**: auth (`verifyAccessToken`, `verifyIdentityToken`, `verifySession`), `ephemeralSigners` (secret-key gated server-side signing), and `funding` (MoonPay onramp signing).
|
|
189
|
+
- **Next**: adds `client.tokens.*` and `client.swaps.*`.
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { AccessTokenClaims, IdentityTokenClaims, PresenceTokenClaims, VerifiedSession } from '@moon-x/core/types';
|
|
2
|
-
export { AccessTokenClaims, BaseTokenClaims, IdentityTokenClaims, PresenceTokenClaims, VerifiedSession } from '@moon-x/core/types';
|
|
1
|
+
import { AccessTokenClaims, IdentityTokenClaims, PresenceTokenClaims, VerifiedSession, MoonPaySignResponse } from '@moon-x/core/types';
|
|
2
|
+
export { AccessTokenClaims, BaseTokenClaims, IdentityTokenClaims, MoonPaySignResponse, PresenceTokenClaims, VerifiedSession } from '@moon-x/core/types';
|
|
3
3
|
import { EphemeralSignerSignResult } from '@moon-x/core/sdk';
|
|
4
4
|
export { EphemeralSignerSignError, EphemeralSignerSignResult } from '@moon-x/core/sdk';
|
|
5
5
|
|
|
@@ -143,6 +143,60 @@ declare class EphemeralSigners {
|
|
|
143
143
|
sign(params: SignEphemeralSignerParams): Promise<EphemeralSignerSignResult>;
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
+
interface FundingConfig {
|
|
147
|
+
baseUrl: string;
|
|
148
|
+
/** App publishable key (`moon_pk_*`). Sent as `Authorization: PublicToken`. */
|
|
149
|
+
publishableKey: string;
|
|
150
|
+
/** Override for tests — defaults to globalThis.fetch. */
|
|
151
|
+
fetchImpl?: typeof fetch;
|
|
152
|
+
}
|
|
153
|
+
/** Optional MoonPay widget theming, forwarded to the Buy widget. */
|
|
154
|
+
interface MoonPaySignUiConfig {
|
|
155
|
+
/** MoonPay widget theme. */
|
|
156
|
+
theme?: "light" | "dark";
|
|
157
|
+
/** Hex accent color for the widget, e.g. `#7C3AED`. */
|
|
158
|
+
accentColor?: string;
|
|
159
|
+
}
|
|
160
|
+
interface MoonPaySignParams {
|
|
161
|
+
/**
|
|
162
|
+
* The end-user's MoonX access token. The route refuses to sign unless
|
|
163
|
+
* `publicAddress` belongs to this user. Read it from your request (the
|
|
164
|
+
* `X-MoonX-Access-Token` header the browser SDK sends).
|
|
165
|
+
*/
|
|
166
|
+
accessToken: string;
|
|
167
|
+
/** Wallet address that will receive the funds. Must belong to the user. */
|
|
168
|
+
publicAddress: string;
|
|
169
|
+
/**
|
|
170
|
+
* Route through MoonPay's sandbox (no real payment). Defaults to `false`
|
|
171
|
+
* (production). Requires the app's sandbox keys, or the platform sandbox
|
|
172
|
+
* defaults, to be configured.
|
|
173
|
+
*/
|
|
174
|
+
useSandbox?: boolean;
|
|
175
|
+
/** MoonPay currency code to preselect, e.g. `"eth"`, `"usdc_sol"`. */
|
|
176
|
+
currencyCode?: string;
|
|
177
|
+
/**
|
|
178
|
+
* Pin the fiat amount to buy. Omit to let the user choose the amount inside
|
|
179
|
+
* the MoonPay widget.
|
|
180
|
+
*/
|
|
181
|
+
quoteCurrencyAmount?: number;
|
|
182
|
+
/** MoonPay payment method to preselect, e.g. `"credit_debit_card"`. */
|
|
183
|
+
paymentMethod?: string;
|
|
184
|
+
/** MoonPay widget theming. */
|
|
185
|
+
uiConfig?: MoonPaySignUiConfig;
|
|
186
|
+
}
|
|
187
|
+
declare class Funding {
|
|
188
|
+
private readonly cfg;
|
|
189
|
+
constructor(cfg: FundingConfig);
|
|
190
|
+
/**
|
|
191
|
+
* Request a signed MoonPay Buy-widget URL for the user's wallet. Returns the
|
|
192
|
+
* `signed_url` to open (plus the transaction id and provider publishable key
|
|
193
|
+
* used to track the purchase). Throws a typed {@link MoonXError} subclass on
|
|
194
|
+
* failure: IntegrationNotConfiguredError (400), UnauthorizedError (401),
|
|
195
|
+
* WalletOwnershipError (403), RateLimitedError (429).
|
|
196
|
+
*/
|
|
197
|
+
sign(params: MoonPaySignParams): Promise<MoonPaySignResponse>;
|
|
198
|
+
}
|
|
199
|
+
|
|
146
200
|
/**
|
|
147
201
|
* MoonXClient is the entry point for the node SDK. Construct once per
|
|
148
202
|
* process and reuse across requests — the client holds in-memory caches
|
|
@@ -165,17 +219,18 @@ declare class EphemeralSigners {
|
|
|
165
219
|
* // session.identity?.email — OIDC profile claim (when identity token sent)
|
|
166
220
|
* // session.identity?.name — etc.
|
|
167
221
|
*
|
|
168
|
-
* Today this ships the `auth` namespace
|
|
169
|
-
*
|
|
170
|
-
* namespaces land in
|
|
222
|
+
* Today this ships the `auth` namespace, `ephemeralSigners` (secret-key
|
|
223
|
+
* gated; see `secretKey`), and `funding` (the MoonPay onramp sign surface).
|
|
224
|
+
* The `tokens` and `swaps` namespaces land in a later release.
|
|
171
225
|
*/
|
|
172
226
|
declare class MoonXClient {
|
|
173
227
|
readonly auth: Auth;
|
|
174
228
|
readonly ephemeralSigners: EphemeralSigners;
|
|
229
|
+
readonly funding: Funding;
|
|
175
230
|
constructor(input: MoonXClientConfig);
|
|
176
231
|
}
|
|
177
232
|
|
|
178
|
-
type MoonXErrorCode = "malformed_token" | "invalid_signature" | "expired_token" | "audience_mismatch" | "issuer_mismatch" | "subject_mismatch" | "kid_mismatch" | "unsupported_algorithm" | "jwks_fetch_failed" | "app_resolution_failed" | "configuration_error";
|
|
233
|
+
type MoonXErrorCode = "malformed_token" | "invalid_signature" | "expired_token" | "audience_mismatch" | "issuer_mismatch" | "subject_mismatch" | "kid_mismatch" | "unsupported_algorithm" | "jwks_fetch_failed" | "app_resolution_failed" | "configuration_error" | "integration_not_configured" | "wallet_ownership" | "rate_limited" | "unauthorized" | "request_failed";
|
|
179
234
|
declare class MoonXError extends Error {
|
|
180
235
|
readonly code: MoonXErrorCode;
|
|
181
236
|
constructor(code: MoonXErrorCode, message: string);
|
|
@@ -213,5 +268,21 @@ declare class AppResolutionError extends MoonXError {
|
|
|
213
268
|
declare class ConfigurationError extends MoonXError {
|
|
214
269
|
constructor(message: string);
|
|
215
270
|
}
|
|
271
|
+
declare class IntegrationNotConfiguredError extends MoonXError {
|
|
272
|
+
constructor(message?: string);
|
|
273
|
+
}
|
|
274
|
+
declare class WalletOwnershipError extends MoonXError {
|
|
275
|
+
constructor(message?: string);
|
|
276
|
+
}
|
|
277
|
+
declare class RateLimitedError extends MoonXError {
|
|
278
|
+
constructor(message?: string);
|
|
279
|
+
}
|
|
280
|
+
declare class UnauthorizedError extends MoonXError {
|
|
281
|
+
constructor(message?: string);
|
|
282
|
+
}
|
|
283
|
+
declare class RequestFailedError extends MoonXError {
|
|
284
|
+
readonly status: number;
|
|
285
|
+
constructor(status: number, message: string);
|
|
286
|
+
}
|
|
216
287
|
|
|
217
|
-
export { AppResolutionError, AudienceMismatchError, ConfigurationError, EphemeralSigners, ExpiredTokenError, InvalidTokenError, IssuerMismatchError, JwksFetchError, KidMismatchError, MalformedTokenError, MoonXClient, type MoonXClientConfig, MoonXError, type MoonXErrorCode, type SignEphemeralSignerParams, SubjectMismatchError, UnsupportedAlgorithmError };
|
|
288
|
+
export { AppResolutionError, AudienceMismatchError, ConfigurationError, EphemeralSigners, ExpiredTokenError, Funding, type FundingConfig, IntegrationNotConfiguredError, InvalidTokenError, IssuerMismatchError, JwksFetchError, KidMismatchError, MalformedTokenError, type MoonPaySignParams, type MoonPaySignUiConfig, MoonXClient, type MoonXClientConfig, MoonXError, type MoonXErrorCode, RateLimitedError, RequestFailedError, type SignEphemeralSignerParams, SubjectMismatchError, UnauthorizedError, UnsupportedAlgorithmError, WalletOwnershipError };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { AccessTokenClaims, IdentityTokenClaims, PresenceTokenClaims, VerifiedSession } from '@moon-x/core/types';
|
|
2
|
-
export { AccessTokenClaims, BaseTokenClaims, IdentityTokenClaims, PresenceTokenClaims, VerifiedSession } from '@moon-x/core/types';
|
|
1
|
+
import { AccessTokenClaims, IdentityTokenClaims, PresenceTokenClaims, VerifiedSession, MoonPaySignResponse } from '@moon-x/core/types';
|
|
2
|
+
export { AccessTokenClaims, BaseTokenClaims, IdentityTokenClaims, MoonPaySignResponse, PresenceTokenClaims, VerifiedSession } from '@moon-x/core/types';
|
|
3
3
|
import { EphemeralSignerSignResult } from '@moon-x/core/sdk';
|
|
4
4
|
export { EphemeralSignerSignError, EphemeralSignerSignResult } from '@moon-x/core/sdk';
|
|
5
5
|
|
|
@@ -143,6 +143,60 @@ declare class EphemeralSigners {
|
|
|
143
143
|
sign(params: SignEphemeralSignerParams): Promise<EphemeralSignerSignResult>;
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
+
interface FundingConfig {
|
|
147
|
+
baseUrl: string;
|
|
148
|
+
/** App publishable key (`moon_pk_*`). Sent as `Authorization: PublicToken`. */
|
|
149
|
+
publishableKey: string;
|
|
150
|
+
/** Override for tests — defaults to globalThis.fetch. */
|
|
151
|
+
fetchImpl?: typeof fetch;
|
|
152
|
+
}
|
|
153
|
+
/** Optional MoonPay widget theming, forwarded to the Buy widget. */
|
|
154
|
+
interface MoonPaySignUiConfig {
|
|
155
|
+
/** MoonPay widget theme. */
|
|
156
|
+
theme?: "light" | "dark";
|
|
157
|
+
/** Hex accent color for the widget, e.g. `#7C3AED`. */
|
|
158
|
+
accentColor?: string;
|
|
159
|
+
}
|
|
160
|
+
interface MoonPaySignParams {
|
|
161
|
+
/**
|
|
162
|
+
* The end-user's MoonX access token. The route refuses to sign unless
|
|
163
|
+
* `publicAddress` belongs to this user. Read it from your request (the
|
|
164
|
+
* `X-MoonX-Access-Token` header the browser SDK sends).
|
|
165
|
+
*/
|
|
166
|
+
accessToken: string;
|
|
167
|
+
/** Wallet address that will receive the funds. Must belong to the user. */
|
|
168
|
+
publicAddress: string;
|
|
169
|
+
/**
|
|
170
|
+
* Route through MoonPay's sandbox (no real payment). Defaults to `false`
|
|
171
|
+
* (production). Requires the app's sandbox keys, or the platform sandbox
|
|
172
|
+
* defaults, to be configured.
|
|
173
|
+
*/
|
|
174
|
+
useSandbox?: boolean;
|
|
175
|
+
/** MoonPay currency code to preselect, e.g. `"eth"`, `"usdc_sol"`. */
|
|
176
|
+
currencyCode?: string;
|
|
177
|
+
/**
|
|
178
|
+
* Pin the fiat amount to buy. Omit to let the user choose the amount inside
|
|
179
|
+
* the MoonPay widget.
|
|
180
|
+
*/
|
|
181
|
+
quoteCurrencyAmount?: number;
|
|
182
|
+
/** MoonPay payment method to preselect, e.g. `"credit_debit_card"`. */
|
|
183
|
+
paymentMethod?: string;
|
|
184
|
+
/** MoonPay widget theming. */
|
|
185
|
+
uiConfig?: MoonPaySignUiConfig;
|
|
186
|
+
}
|
|
187
|
+
declare class Funding {
|
|
188
|
+
private readonly cfg;
|
|
189
|
+
constructor(cfg: FundingConfig);
|
|
190
|
+
/**
|
|
191
|
+
* Request a signed MoonPay Buy-widget URL for the user's wallet. Returns the
|
|
192
|
+
* `signed_url` to open (plus the transaction id and provider publishable key
|
|
193
|
+
* used to track the purchase). Throws a typed {@link MoonXError} subclass on
|
|
194
|
+
* failure: IntegrationNotConfiguredError (400), UnauthorizedError (401),
|
|
195
|
+
* WalletOwnershipError (403), RateLimitedError (429).
|
|
196
|
+
*/
|
|
197
|
+
sign(params: MoonPaySignParams): Promise<MoonPaySignResponse>;
|
|
198
|
+
}
|
|
199
|
+
|
|
146
200
|
/**
|
|
147
201
|
* MoonXClient is the entry point for the node SDK. Construct once per
|
|
148
202
|
* process and reuse across requests — the client holds in-memory caches
|
|
@@ -165,17 +219,18 @@ declare class EphemeralSigners {
|
|
|
165
219
|
* // session.identity?.email — OIDC profile claim (when identity token sent)
|
|
166
220
|
* // session.identity?.name — etc.
|
|
167
221
|
*
|
|
168
|
-
* Today this ships the `auth` namespace
|
|
169
|
-
*
|
|
170
|
-
* namespaces land in
|
|
222
|
+
* Today this ships the `auth` namespace, `ephemeralSigners` (secret-key
|
|
223
|
+
* gated; see `secretKey`), and `funding` (the MoonPay onramp sign surface).
|
|
224
|
+
* The `tokens` and `swaps` namespaces land in a later release.
|
|
171
225
|
*/
|
|
172
226
|
declare class MoonXClient {
|
|
173
227
|
readonly auth: Auth;
|
|
174
228
|
readonly ephemeralSigners: EphemeralSigners;
|
|
229
|
+
readonly funding: Funding;
|
|
175
230
|
constructor(input: MoonXClientConfig);
|
|
176
231
|
}
|
|
177
232
|
|
|
178
|
-
type MoonXErrorCode = "malformed_token" | "invalid_signature" | "expired_token" | "audience_mismatch" | "issuer_mismatch" | "subject_mismatch" | "kid_mismatch" | "unsupported_algorithm" | "jwks_fetch_failed" | "app_resolution_failed" | "configuration_error";
|
|
233
|
+
type MoonXErrorCode = "malformed_token" | "invalid_signature" | "expired_token" | "audience_mismatch" | "issuer_mismatch" | "subject_mismatch" | "kid_mismatch" | "unsupported_algorithm" | "jwks_fetch_failed" | "app_resolution_failed" | "configuration_error" | "integration_not_configured" | "wallet_ownership" | "rate_limited" | "unauthorized" | "request_failed";
|
|
179
234
|
declare class MoonXError extends Error {
|
|
180
235
|
readonly code: MoonXErrorCode;
|
|
181
236
|
constructor(code: MoonXErrorCode, message: string);
|
|
@@ -213,5 +268,21 @@ declare class AppResolutionError extends MoonXError {
|
|
|
213
268
|
declare class ConfigurationError extends MoonXError {
|
|
214
269
|
constructor(message: string);
|
|
215
270
|
}
|
|
271
|
+
declare class IntegrationNotConfiguredError extends MoonXError {
|
|
272
|
+
constructor(message?: string);
|
|
273
|
+
}
|
|
274
|
+
declare class WalletOwnershipError extends MoonXError {
|
|
275
|
+
constructor(message?: string);
|
|
276
|
+
}
|
|
277
|
+
declare class RateLimitedError extends MoonXError {
|
|
278
|
+
constructor(message?: string);
|
|
279
|
+
}
|
|
280
|
+
declare class UnauthorizedError extends MoonXError {
|
|
281
|
+
constructor(message?: string);
|
|
282
|
+
}
|
|
283
|
+
declare class RequestFailedError extends MoonXError {
|
|
284
|
+
readonly status: number;
|
|
285
|
+
constructor(status: number, message: string);
|
|
286
|
+
}
|
|
216
287
|
|
|
217
|
-
export { AppResolutionError, AudienceMismatchError, ConfigurationError, EphemeralSigners, ExpiredTokenError, InvalidTokenError, IssuerMismatchError, JwksFetchError, KidMismatchError, MalformedTokenError, MoonXClient, type MoonXClientConfig, MoonXError, type MoonXErrorCode, type SignEphemeralSignerParams, SubjectMismatchError, UnsupportedAlgorithmError };
|
|
288
|
+
export { AppResolutionError, AudienceMismatchError, ConfigurationError, EphemeralSigners, ExpiredTokenError, Funding, type FundingConfig, IntegrationNotConfiguredError, InvalidTokenError, IssuerMismatchError, JwksFetchError, KidMismatchError, MalformedTokenError, type MoonPaySignParams, type MoonPaySignUiConfig, MoonXClient, type MoonXClientConfig, MoonXError, type MoonXErrorCode, RateLimitedError, RequestFailedError, type SignEphemeralSignerParams, SubjectMismatchError, UnauthorizedError, UnsupportedAlgorithmError, WalletOwnershipError };
|
package/dist/index.js
CHANGED
|
@@ -26,6 +26,8 @@ __export(src_exports, {
|
|
|
26
26
|
EphemeralSignerSignError: () => import_sdk3.EphemeralSignerSignError,
|
|
27
27
|
EphemeralSigners: () => EphemeralSigners,
|
|
28
28
|
ExpiredTokenError: () => ExpiredTokenError,
|
|
29
|
+
Funding: () => Funding,
|
|
30
|
+
IntegrationNotConfiguredError: () => IntegrationNotConfiguredError,
|
|
29
31
|
InvalidTokenError: () => InvalidTokenError,
|
|
30
32
|
IssuerMismatchError: () => IssuerMismatchError,
|
|
31
33
|
JwksFetchError: () => JwksFetchError,
|
|
@@ -33,8 +35,12 @@ __export(src_exports, {
|
|
|
33
35
|
MalformedTokenError: () => MalformedTokenError,
|
|
34
36
|
MoonXClient: () => MoonXClient,
|
|
35
37
|
MoonXError: () => MoonXError,
|
|
38
|
+
RateLimitedError: () => RateLimitedError,
|
|
39
|
+
RequestFailedError: () => RequestFailedError,
|
|
36
40
|
SubjectMismatchError: () => SubjectMismatchError,
|
|
37
|
-
|
|
41
|
+
UnauthorizedError: () => UnauthorizedError,
|
|
42
|
+
UnsupportedAlgorithmError: () => UnsupportedAlgorithmError,
|
|
43
|
+
WalletOwnershipError: () => WalletOwnershipError
|
|
38
44
|
});
|
|
39
45
|
module.exports = __toCommonJS(src_exports);
|
|
40
46
|
|
|
@@ -127,6 +133,42 @@ var ConfigurationError = class extends MoonXError {
|
|
|
127
133
|
Object.setPrototypeOf(this, new.target.prototype);
|
|
128
134
|
}
|
|
129
135
|
};
|
|
136
|
+
var IntegrationNotConfiguredError = class extends MoonXError {
|
|
137
|
+
constructor(message = "MoonPay funding is not configured or is disabled for this app") {
|
|
138
|
+
super("integration_not_configured", message);
|
|
139
|
+
this.name = "IntegrationNotConfiguredError";
|
|
140
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
var WalletOwnershipError = class extends MoonXError {
|
|
144
|
+
constructor(message = "wallet address does not belong to this user") {
|
|
145
|
+
super("wallet_ownership", message);
|
|
146
|
+
this.name = "WalletOwnershipError";
|
|
147
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
var RateLimitedError = class extends MoonXError {
|
|
151
|
+
constructor(message = "request was rate limited") {
|
|
152
|
+
super("rate_limited", message);
|
|
153
|
+
this.name = "RateLimitedError";
|
|
154
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
var UnauthorizedError = class extends MoonXError {
|
|
158
|
+
constructor(message = "missing or invalid credentials") {
|
|
159
|
+
super("unauthorized", message);
|
|
160
|
+
this.name = "UnauthorizedError";
|
|
161
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
var RequestFailedError = class extends MoonXError {
|
|
165
|
+
constructor(status, message) {
|
|
166
|
+
super("request_failed", message);
|
|
167
|
+
this.name = "RequestFailedError";
|
|
168
|
+
this.status = status;
|
|
169
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
170
|
+
}
|
|
171
|
+
};
|
|
130
172
|
|
|
131
173
|
// src/auth/app-resolver.ts
|
|
132
174
|
var AppResolver = class {
|
|
@@ -529,6 +571,111 @@ var EphemeralSigners = class {
|
|
|
529
571
|
}
|
|
530
572
|
};
|
|
531
573
|
|
|
574
|
+
// src/funding/sign.ts
|
|
575
|
+
async function signMoonPay(args) {
|
|
576
|
+
if (!args.accessToken || !args.accessToken.trim()) {
|
|
577
|
+
throw new ConfigurationError("funding.sign: accessToken is required");
|
|
578
|
+
}
|
|
579
|
+
if (!args.publicAddress || !args.publicAddress.trim()) {
|
|
580
|
+
throw new ConfigurationError("funding.sign: publicAddress is required");
|
|
581
|
+
}
|
|
582
|
+
if (args.uiConfig?.theme !== void 0 && args.uiConfig.theme !== "light" && args.uiConfig.theme !== "dark") {
|
|
583
|
+
throw new ConfigurationError(
|
|
584
|
+
'funding.sign: uiConfig.theme must be "light" or "dark"'
|
|
585
|
+
);
|
|
586
|
+
}
|
|
587
|
+
const fetcher = args.fetchImpl ?? globalThis.fetch;
|
|
588
|
+
const url = `${args.baseUrl.replace(/\/$/, "")}/v0/sdk/onramps/public/moonpay/sign`;
|
|
589
|
+
const config = {};
|
|
590
|
+
if (args.currencyCode !== void 0) config.currency_code = args.currencyCode;
|
|
591
|
+
if (args.quoteCurrencyAmount !== void 0) {
|
|
592
|
+
config.quote_currency_amount = args.quoteCurrencyAmount;
|
|
593
|
+
}
|
|
594
|
+
if (args.paymentMethod !== void 0) {
|
|
595
|
+
config.payment_method = args.paymentMethod;
|
|
596
|
+
}
|
|
597
|
+
if (args.uiConfig) {
|
|
598
|
+
const uiConfig = {};
|
|
599
|
+
if (args.uiConfig.theme !== void 0) uiConfig.theme = args.uiConfig.theme;
|
|
600
|
+
if (args.uiConfig.accentColor !== void 0) {
|
|
601
|
+
uiConfig.accent_color = args.uiConfig.accentColor;
|
|
602
|
+
}
|
|
603
|
+
if (Object.keys(uiConfig).length > 0) config.ui_config = uiConfig;
|
|
604
|
+
}
|
|
605
|
+
const body = {
|
|
606
|
+
public_address: args.publicAddress,
|
|
607
|
+
use_sandbox: args.useSandbox ?? false
|
|
608
|
+
};
|
|
609
|
+
if (Object.keys(config).length > 0) body.config = config;
|
|
610
|
+
let res;
|
|
611
|
+
try {
|
|
612
|
+
res = await fetcher(url, {
|
|
613
|
+
method: "POST",
|
|
614
|
+
headers: {
|
|
615
|
+
"Content-Type": "application/json",
|
|
616
|
+
Authorization: `PublicToken ${args.publishableKey}`,
|
|
617
|
+
"X-MoonX-Access-Token": args.accessToken
|
|
618
|
+
},
|
|
619
|
+
body: JSON.stringify(body),
|
|
620
|
+
signal: AbortSignal.timeout(1e4)
|
|
621
|
+
});
|
|
622
|
+
} catch (err) {
|
|
623
|
+
throw new RequestFailedError(
|
|
624
|
+
0,
|
|
625
|
+
`moonpay sign request failed: ${err instanceof Error ? err.message : String(err)}`
|
|
626
|
+
);
|
|
627
|
+
}
|
|
628
|
+
if (!res.ok) {
|
|
629
|
+
const message = await errorMessage(res);
|
|
630
|
+
switch (res.status) {
|
|
631
|
+
case 400:
|
|
632
|
+
throw new IntegrationNotConfiguredError(message || void 0);
|
|
633
|
+
case 401:
|
|
634
|
+
throw new UnauthorizedError(message || void 0);
|
|
635
|
+
case 403:
|
|
636
|
+
throw new WalletOwnershipError(message || void 0);
|
|
637
|
+
case 429:
|
|
638
|
+
throw new RateLimitedError(message || void 0);
|
|
639
|
+
default:
|
|
640
|
+
throw new RequestFailedError(
|
|
641
|
+
res.status,
|
|
642
|
+
`moonpay sign failed: HTTP ${res.status}${message ? `: ${message}` : ""}`
|
|
643
|
+
);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
return await res.json();
|
|
647
|
+
}
|
|
648
|
+
async function errorMessage(res) {
|
|
649
|
+
try {
|
|
650
|
+
const body = await res.json();
|
|
651
|
+
return body.error ?? body.message ?? "";
|
|
652
|
+
} catch {
|
|
653
|
+
return "";
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
// src/funding/index.ts
|
|
658
|
+
var Funding = class {
|
|
659
|
+
constructor(cfg) {
|
|
660
|
+
this.cfg = cfg;
|
|
661
|
+
}
|
|
662
|
+
/**
|
|
663
|
+
* Request a signed MoonPay Buy-widget URL for the user's wallet. Returns the
|
|
664
|
+
* `signed_url` to open (plus the transaction id and provider publishable key
|
|
665
|
+
* used to track the purchase). Throws a typed {@link MoonXError} subclass on
|
|
666
|
+
* failure: IntegrationNotConfiguredError (400), UnauthorizedError (401),
|
|
667
|
+
* WalletOwnershipError (403), RateLimitedError (429).
|
|
668
|
+
*/
|
|
669
|
+
async sign(params) {
|
|
670
|
+
return signMoonPay({
|
|
671
|
+
...params,
|
|
672
|
+
baseUrl: this.cfg.baseUrl,
|
|
673
|
+
publishableKey: this.cfg.publishableKey,
|
|
674
|
+
fetchImpl: this.cfg.fetchImpl
|
|
675
|
+
});
|
|
676
|
+
}
|
|
677
|
+
};
|
|
678
|
+
|
|
532
679
|
// src/client.ts
|
|
533
680
|
var MoonXClient = class {
|
|
534
681
|
constructor(input) {
|
|
@@ -546,6 +693,11 @@ var MoonXClient = class {
|
|
|
546
693
|
secretKey: cfg.secretKey,
|
|
547
694
|
fetchImpl: cfg.fetch
|
|
548
695
|
});
|
|
696
|
+
this.funding = new Funding({
|
|
697
|
+
baseUrl: cfg.baseUrl,
|
|
698
|
+
publishableKey: cfg.publishableKey,
|
|
699
|
+
fetchImpl: cfg.fetch
|
|
700
|
+
});
|
|
549
701
|
}
|
|
550
702
|
};
|
|
551
703
|
|
|
@@ -559,6 +711,8 @@ var import_sdk3 = require("@moon-x/core/sdk");
|
|
|
559
711
|
EphemeralSignerSignError,
|
|
560
712
|
EphemeralSigners,
|
|
561
713
|
ExpiredTokenError,
|
|
714
|
+
Funding,
|
|
715
|
+
IntegrationNotConfiguredError,
|
|
562
716
|
InvalidTokenError,
|
|
563
717
|
IssuerMismatchError,
|
|
564
718
|
JwksFetchError,
|
|
@@ -566,6 +720,10 @@ var import_sdk3 = require("@moon-x/core/sdk");
|
|
|
566
720
|
MalformedTokenError,
|
|
567
721
|
MoonXClient,
|
|
568
722
|
MoonXError,
|
|
723
|
+
RateLimitedError,
|
|
724
|
+
RequestFailedError,
|
|
569
725
|
SubjectMismatchError,
|
|
570
|
-
|
|
726
|
+
UnauthorizedError,
|
|
727
|
+
UnsupportedAlgorithmError,
|
|
728
|
+
WalletOwnershipError
|
|
571
729
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -87,6 +87,42 @@ var ConfigurationError = class extends MoonXError {
|
|
|
87
87
|
Object.setPrototypeOf(this, new.target.prototype);
|
|
88
88
|
}
|
|
89
89
|
};
|
|
90
|
+
var IntegrationNotConfiguredError = class extends MoonXError {
|
|
91
|
+
constructor(message = "MoonPay funding is not configured or is disabled for this app") {
|
|
92
|
+
super("integration_not_configured", message);
|
|
93
|
+
this.name = "IntegrationNotConfiguredError";
|
|
94
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
var WalletOwnershipError = class extends MoonXError {
|
|
98
|
+
constructor(message = "wallet address does not belong to this user") {
|
|
99
|
+
super("wallet_ownership", message);
|
|
100
|
+
this.name = "WalletOwnershipError";
|
|
101
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
var RateLimitedError = class extends MoonXError {
|
|
105
|
+
constructor(message = "request was rate limited") {
|
|
106
|
+
super("rate_limited", message);
|
|
107
|
+
this.name = "RateLimitedError";
|
|
108
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
var UnauthorizedError = class extends MoonXError {
|
|
112
|
+
constructor(message = "missing or invalid credentials") {
|
|
113
|
+
super("unauthorized", message);
|
|
114
|
+
this.name = "UnauthorizedError";
|
|
115
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
var RequestFailedError = class extends MoonXError {
|
|
119
|
+
constructor(status, message) {
|
|
120
|
+
super("request_failed", message);
|
|
121
|
+
this.name = "RequestFailedError";
|
|
122
|
+
this.status = status;
|
|
123
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
124
|
+
}
|
|
125
|
+
};
|
|
90
126
|
|
|
91
127
|
// src/auth/app-resolver.ts
|
|
92
128
|
var AppResolver = class {
|
|
@@ -491,6 +527,111 @@ var EphemeralSigners = class {
|
|
|
491
527
|
}
|
|
492
528
|
};
|
|
493
529
|
|
|
530
|
+
// src/funding/sign.ts
|
|
531
|
+
async function signMoonPay(args) {
|
|
532
|
+
if (!args.accessToken || !args.accessToken.trim()) {
|
|
533
|
+
throw new ConfigurationError("funding.sign: accessToken is required");
|
|
534
|
+
}
|
|
535
|
+
if (!args.publicAddress || !args.publicAddress.trim()) {
|
|
536
|
+
throw new ConfigurationError("funding.sign: publicAddress is required");
|
|
537
|
+
}
|
|
538
|
+
if (args.uiConfig?.theme !== void 0 && args.uiConfig.theme !== "light" && args.uiConfig.theme !== "dark") {
|
|
539
|
+
throw new ConfigurationError(
|
|
540
|
+
'funding.sign: uiConfig.theme must be "light" or "dark"'
|
|
541
|
+
);
|
|
542
|
+
}
|
|
543
|
+
const fetcher = args.fetchImpl ?? globalThis.fetch;
|
|
544
|
+
const url = `${args.baseUrl.replace(/\/$/, "")}/v0/sdk/onramps/public/moonpay/sign`;
|
|
545
|
+
const config = {};
|
|
546
|
+
if (args.currencyCode !== void 0) config.currency_code = args.currencyCode;
|
|
547
|
+
if (args.quoteCurrencyAmount !== void 0) {
|
|
548
|
+
config.quote_currency_amount = args.quoteCurrencyAmount;
|
|
549
|
+
}
|
|
550
|
+
if (args.paymentMethod !== void 0) {
|
|
551
|
+
config.payment_method = args.paymentMethod;
|
|
552
|
+
}
|
|
553
|
+
if (args.uiConfig) {
|
|
554
|
+
const uiConfig = {};
|
|
555
|
+
if (args.uiConfig.theme !== void 0) uiConfig.theme = args.uiConfig.theme;
|
|
556
|
+
if (args.uiConfig.accentColor !== void 0) {
|
|
557
|
+
uiConfig.accent_color = args.uiConfig.accentColor;
|
|
558
|
+
}
|
|
559
|
+
if (Object.keys(uiConfig).length > 0) config.ui_config = uiConfig;
|
|
560
|
+
}
|
|
561
|
+
const body = {
|
|
562
|
+
public_address: args.publicAddress,
|
|
563
|
+
use_sandbox: args.useSandbox ?? false
|
|
564
|
+
};
|
|
565
|
+
if (Object.keys(config).length > 0) body.config = config;
|
|
566
|
+
let res;
|
|
567
|
+
try {
|
|
568
|
+
res = await fetcher(url, {
|
|
569
|
+
method: "POST",
|
|
570
|
+
headers: {
|
|
571
|
+
"Content-Type": "application/json",
|
|
572
|
+
Authorization: `PublicToken ${args.publishableKey}`,
|
|
573
|
+
"X-MoonX-Access-Token": args.accessToken
|
|
574
|
+
},
|
|
575
|
+
body: JSON.stringify(body),
|
|
576
|
+
signal: AbortSignal.timeout(1e4)
|
|
577
|
+
});
|
|
578
|
+
} catch (err) {
|
|
579
|
+
throw new RequestFailedError(
|
|
580
|
+
0,
|
|
581
|
+
`moonpay sign request failed: ${err instanceof Error ? err.message : String(err)}`
|
|
582
|
+
);
|
|
583
|
+
}
|
|
584
|
+
if (!res.ok) {
|
|
585
|
+
const message = await errorMessage(res);
|
|
586
|
+
switch (res.status) {
|
|
587
|
+
case 400:
|
|
588
|
+
throw new IntegrationNotConfiguredError(message || void 0);
|
|
589
|
+
case 401:
|
|
590
|
+
throw new UnauthorizedError(message || void 0);
|
|
591
|
+
case 403:
|
|
592
|
+
throw new WalletOwnershipError(message || void 0);
|
|
593
|
+
case 429:
|
|
594
|
+
throw new RateLimitedError(message || void 0);
|
|
595
|
+
default:
|
|
596
|
+
throw new RequestFailedError(
|
|
597
|
+
res.status,
|
|
598
|
+
`moonpay sign failed: HTTP ${res.status}${message ? `: ${message}` : ""}`
|
|
599
|
+
);
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
return await res.json();
|
|
603
|
+
}
|
|
604
|
+
async function errorMessage(res) {
|
|
605
|
+
try {
|
|
606
|
+
const body = await res.json();
|
|
607
|
+
return body.error ?? body.message ?? "";
|
|
608
|
+
} catch {
|
|
609
|
+
return "";
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
// src/funding/index.ts
|
|
614
|
+
var Funding = class {
|
|
615
|
+
constructor(cfg) {
|
|
616
|
+
this.cfg = cfg;
|
|
617
|
+
}
|
|
618
|
+
/**
|
|
619
|
+
* Request a signed MoonPay Buy-widget URL for the user's wallet. Returns the
|
|
620
|
+
* `signed_url` to open (plus the transaction id and provider publishable key
|
|
621
|
+
* used to track the purchase). Throws a typed {@link MoonXError} subclass on
|
|
622
|
+
* failure: IntegrationNotConfiguredError (400), UnauthorizedError (401),
|
|
623
|
+
* WalletOwnershipError (403), RateLimitedError (429).
|
|
624
|
+
*/
|
|
625
|
+
async sign(params) {
|
|
626
|
+
return signMoonPay({
|
|
627
|
+
...params,
|
|
628
|
+
baseUrl: this.cfg.baseUrl,
|
|
629
|
+
publishableKey: this.cfg.publishableKey,
|
|
630
|
+
fetchImpl: this.cfg.fetchImpl
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
};
|
|
634
|
+
|
|
494
635
|
// src/client.ts
|
|
495
636
|
var MoonXClient = class {
|
|
496
637
|
constructor(input) {
|
|
@@ -508,6 +649,11 @@ var MoonXClient = class {
|
|
|
508
649
|
secretKey: cfg.secretKey,
|
|
509
650
|
fetchImpl: cfg.fetch
|
|
510
651
|
});
|
|
652
|
+
this.funding = new Funding({
|
|
653
|
+
baseUrl: cfg.baseUrl,
|
|
654
|
+
publishableKey: cfg.publishableKey,
|
|
655
|
+
fetchImpl: cfg.fetch
|
|
656
|
+
});
|
|
511
657
|
}
|
|
512
658
|
};
|
|
513
659
|
|
|
@@ -522,6 +668,8 @@ export {
|
|
|
522
668
|
EphemeralSignerSignError,
|
|
523
669
|
EphemeralSigners,
|
|
524
670
|
ExpiredTokenError,
|
|
671
|
+
Funding,
|
|
672
|
+
IntegrationNotConfiguredError,
|
|
525
673
|
InvalidTokenError,
|
|
526
674
|
IssuerMismatchError,
|
|
527
675
|
JwksFetchError,
|
|
@@ -529,6 +677,10 @@ export {
|
|
|
529
677
|
MalformedTokenError,
|
|
530
678
|
MoonXClient,
|
|
531
679
|
MoonXError,
|
|
680
|
+
RateLimitedError,
|
|
681
|
+
RequestFailedError,
|
|
532
682
|
SubjectMismatchError,
|
|
533
|
-
|
|
683
|
+
UnauthorizedError,
|
|
684
|
+
UnsupportedAlgorithmError,
|
|
685
|
+
WalletOwnershipError
|
|
534
686
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moon-x/node-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "MoonX server-side SDK for Node.js. Verify MoonX-issued access + identity tokens with zero runtime dependencies.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"access": "public"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@moon-x/core": "0.
|
|
33
|
+
"@moon-x/core": "0.14.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"tsup": "8.5.1",
|