@iamgame/wallet-sdk-server 0.1.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 ADDED
@@ -0,0 +1,28 @@
1
+ # @iamgame/wallet-sdk-server
2
+
3
+ Backend SDK for [IAMGame Wallet](https://wallet.iamgame.com). Authenticated with your **secret
4
+ key** (`sk_`) — server-to-server only. Two jobs: **verify wallet sessions** at login, and run the
5
+ **high-frequency money ledger**. The browser must never hold an `sk_` or call `win` on itself.
6
+
7
+ All amounts are `bigint` integer base units (lamports / micro-USDC).
8
+
9
+ ```ts
10
+ import { IAMGameWalletServer } from "@iamgame/wallet-sdk-server";
11
+
12
+ const wallet = new IAMGameWalletServer({
13
+ secretKey: process.env.IAMGAME_WALLET_SECRET_KEY!, // sk_live_... / sk_test_...
14
+ baseUrl: "https://api-wallet.iamgame.com/v1",
15
+ });
16
+
17
+ // Login: verify the player's session token, then mint your own app JWT.
18
+ const verified = await wallet.verifySession(sessionToken);
19
+ // → { userId, walletAddress, wallets, identities, environment }
20
+
21
+ // Ledger: lock once, run the hot path, settle the net.
22
+ const s = await wallet.ledger.openSession({ userId, gameCode: "momentum", currency: "USDC", lockAmount: 50_000_000n });
23
+ await wallet.ledger.bet({ sessionToken: s.sessionToken, transactionUuid: "r1-bet", amount: 1_000_000n, round: "r1" });
24
+ await wallet.ledger.win({ sessionToken: s.sessionToken, transactionUuid: "r1-win", referenceTransactionUuid: "r1-bet", amount: 1_800_000n, round: "r1", roundClosed: true });
25
+ const { payout } = await wallet.ledger.settleSession(s.sessionToken);
26
+ ```
27
+
28
+ See the full guide at https://wallet.iamgame.com/docs.
package/dist/index.cjs ADDED
@@ -0,0 +1,151 @@
1
+ 'use strict';
2
+
3
+ // ../../solven/sdk-server/src/errors.ts
4
+ var SolvenServerError = class _SolvenServerError extends Error {
5
+ constructor(args) {
6
+ super(args.message);
7
+ this.name = "SolvenServerError";
8
+ this.code = args.code;
9
+ this.httpStatus = args.httpStatus;
10
+ this.details = args.details;
11
+ }
12
+ static fromEnvelope(httpStatus, env) {
13
+ return new _SolvenServerError({
14
+ code: env.code,
15
+ message: env.message,
16
+ httpStatus,
17
+ details: env.details
18
+ });
19
+ }
20
+ };
21
+
22
+ // ../../solven/sdk-server/src/client.ts
23
+ var LedgerApi = class {
24
+ constructor(call) {
25
+ this.call = call;
26
+ }
27
+ async openSession(args) {
28
+ const r = await this.call("/ledger/sessions", {
29
+ userId: args.userId,
30
+ gameCode: args.gameCode,
31
+ currency: args.currency,
32
+ lockAmount: args.lockAmount.toString()
33
+ });
34
+ return {
35
+ sessionToken: r.sessionToken,
36
+ sessionId: r.sessionId,
37
+ currency: r.currency,
38
+ lockedBalance: BigInt(r.lockedBalance),
39
+ balance: BigInt(r.balance)
40
+ };
41
+ }
42
+ async bet(args) {
43
+ return this.txn("/ledger/bet", {
44
+ sessionToken: args.sessionToken,
45
+ transactionUuid: args.transactionUuid,
46
+ amount: args.amount.toString(),
47
+ round: args.round,
48
+ roundClosed: args.roundClosed
49
+ });
50
+ }
51
+ async win(args) {
52
+ return this.txn("/ledger/win", {
53
+ sessionToken: args.sessionToken,
54
+ transactionUuid: args.transactionUuid,
55
+ referenceTransactionUuid: args.referenceTransactionUuid,
56
+ amount: args.amount.toString(),
57
+ round: args.round,
58
+ roundClosed: args.roundClosed
59
+ });
60
+ }
61
+ async rollback(args) {
62
+ return this.txn("/ledger/rollback", {
63
+ sessionToken: args.sessionToken,
64
+ referenceTransactionUuid: args.referenceTransactionUuid,
65
+ round: args.round
66
+ });
67
+ }
68
+ async balance(sessionToken) {
69
+ const r = await this.call("/ledger/balance", { sessionToken });
70
+ return { balance: BigInt(r.balance), currency: r.currency };
71
+ }
72
+ async settleSession(sessionToken) {
73
+ const r = await this.call(
74
+ "/ledger/settle",
75
+ { sessionToken }
76
+ );
77
+ return { sessionId: r.sessionId, currency: r.currency, payout: BigInt(r.payout), railRef: r.railRef };
78
+ }
79
+ async txn(path, body) {
80
+ const r = await this.call(
81
+ path,
82
+ body
83
+ );
84
+ return { transactionUuid: r.transactionUuid, balance: BigInt(r.balance), currency: r.currency, applied: r.applied };
85
+ }
86
+ };
87
+ var SolvenServer = class {
88
+ constructor(options) {
89
+ if (!options.secretKey.startsWith("sk_")) {
90
+ throw new Error("SolvenServer requires a secret key (sk_...)");
91
+ }
92
+ this.secretKey = options.secretKey;
93
+ this.baseUrl = options.baseUrl.replace(/\/$/, "");
94
+ this.fetchImpl = options.fetchImpl ?? globalThis.fetch.bind(globalThis);
95
+ this.ledger = new LedgerApi((path, body) => this.call(path, body));
96
+ }
97
+ /**
98
+ * Verify a player's wallet session token server-to-server and return the canonical
99
+ * verified identity (scoped to this key's app + environment). Call this from your
100
+ * backend with the token your frontend received from the wallet, then mint your own
101
+ * app JWT for the returned user. Throws if the session is invalid or scoped elsewhere.
102
+ */
103
+ async verifySession(sessionToken) {
104
+ return this.call("/sessions/verify", { sessionToken });
105
+ }
106
+ async call(path, body) {
107
+ let resp;
108
+ try {
109
+ resp = await this.fetchImpl(`${this.baseUrl}${path}`, {
110
+ method: "POST",
111
+ headers: {
112
+ authorization: `Bearer ${this.secretKey}`,
113
+ "content-type": "application/json"
114
+ },
115
+ body: JSON.stringify(body ?? {})
116
+ });
117
+ } catch (err) {
118
+ throw new SolvenServerError({
119
+ code: "client/network",
120
+ message: err instanceof Error ? err.message : "network error",
121
+ httpStatus: 0
122
+ });
123
+ }
124
+ const text = await resp.text();
125
+ let json = void 0;
126
+ if (text) {
127
+ try {
128
+ json = JSON.parse(text);
129
+ } catch {
130
+ throw new SolvenServerError({
131
+ code: "client/bad_response",
132
+ message: `non-JSON response (${resp.status})`,
133
+ httpStatus: resp.status
134
+ });
135
+ }
136
+ }
137
+ if (!resp.ok) {
138
+ const env = json?.error;
139
+ if (env?.code) throw SolvenServerError.fromEnvelope(resp.status, env);
140
+ throw new SolvenServerError({
141
+ code: "client/bad_response",
142
+ message: `request failed (${resp.status})`,
143
+ httpStatus: resp.status
144
+ });
145
+ }
146
+ return json;
147
+ }
148
+ };
149
+
150
+ exports.IAMGameWalletServer = SolvenServer;
151
+ exports.WalletServerError = SolvenServerError;
@@ -0,0 +1,137 @@
1
+ type AuthMethod = "siws" | "telegram";
2
+ interface IUserIdentity {
3
+ id: string;
4
+ type: AuthMethod;
5
+ /** For SIWS: base58 Solana pubkey. For Telegram: numeric user id as string. */
6
+ externalId: string;
7
+ }
8
+ interface IUserWallet {
9
+ /** base58 Solana pubkey */
10
+ address: string;
11
+ /** test (devnet) or live (mainnet) — wallets are isolated per environment. */
12
+ environment: "test" | "live";
13
+ custody: "self" | "operator";
14
+ status: "active" | "exported" | "archived";
15
+ }
16
+ /**
17
+ * Result of a server-to-server session verification (POST /v1/sessions/verify).
18
+ * A relying party (game backend) presents a player's wallet session token together
19
+ * with its own secret key; the wallet confirms the session, scopes it to the caller's
20
+ * app + environment, and returns the canonical user identity. The relying party then
21
+ * mints its OWN app JWT for its UI, trusting this verified identity.
22
+ */
23
+ interface ISessionVerification {
24
+ userId: string;
25
+ appId: string;
26
+ environment: "test" | "live";
27
+ authMethod: AuthMethod;
28
+ /** Primary active wallet address for this user, or null if none provisioned yet. */
29
+ walletAddress: string | null;
30
+ wallets: IUserWallet[];
31
+ identities: IUserIdentity[];
32
+ }
33
+
34
+ type IAMGameErrorCode = "auth/invalid_signature" | "auth/challenge_expired" | "auth/challenge_already_redeemed" | "auth/invalid_init_data" | "auth/init_data_stale" | "auth/init_data_replayed" | "auth/missing_token" | "auth/invalid_token" | "auth/expired_token" | "wallet/not_found" | "wallet/insufficient_balance" | "wallet/export_blocked" | "wallet/already_exported" | "user/not_found" | "user/suspended" | "compliance/blocked" | "sign/invalid_transaction" | "sign/wallet_archived" | "sign/internal_failure" | "withdrawal/insufficient_balance" | "withdrawal/limit_exceeded" | "ledger/insufficient_balance" | "ledger/session_not_found" | "ledger/session_closed" | "ledger/bet_not_found" | "ledger/bet_rolled_back" | "ledger/currency_mismatch" | "ratelimit/exceeded" | "idempotency/key_in_use" | "validation/bad_request" | "server/internal";
35
+ interface IIAMGameErrorEnvelope {
36
+ code: IAMGameErrorCode;
37
+ message: string;
38
+ details?: Record<string, unknown>;
39
+ }
40
+
41
+ interface IAMGameServerOptions {
42
+ /** Secret key, e.g. "sk_live_..." or "sk_test_...". */
43
+ secretKey: string;
44
+ /** Base URL incl. version path, e.g. "https://api-wallet.iamgame.com/v1". */
45
+ baseUrl: string;
46
+ fetchImpl?: typeof fetch;
47
+ }
48
+ interface OpenSessionArgs {
49
+ userId: string;
50
+ gameCode: string;
51
+ currency: string;
52
+ lockAmount: bigint;
53
+ }
54
+ interface OpenSessionResult {
55
+ sessionToken: string;
56
+ sessionId: string;
57
+ currency: string;
58
+ lockedBalance: bigint;
59
+ balance: bigint;
60
+ }
61
+ interface BetArgs {
62
+ sessionToken: string;
63
+ transactionUuid: string;
64
+ amount: bigint;
65
+ round?: string;
66
+ roundClosed?: boolean;
67
+ }
68
+ interface WinArgs {
69
+ sessionToken: string;
70
+ transactionUuid: string;
71
+ referenceTransactionUuid: string;
72
+ amount: bigint;
73
+ round?: string;
74
+ roundClosed?: boolean;
75
+ }
76
+ interface RollbackArgs {
77
+ sessionToken: string;
78
+ referenceTransactionUuid: string;
79
+ round?: string;
80
+ }
81
+ interface TxnResult {
82
+ transactionUuid: string;
83
+ balance: bigint;
84
+ currency: string;
85
+ applied: boolean;
86
+ }
87
+ interface BalanceResult {
88
+ balance: bigint;
89
+ currency: string;
90
+ }
91
+ interface SettleResult {
92
+ sessionId: string;
93
+ currency: string;
94
+ payout: bigint;
95
+ railRef: string | null;
96
+ }
97
+ declare class LedgerApi {
98
+ private readonly call;
99
+ constructor(call: <T>(path: string, body: unknown) => Promise<T>);
100
+ openSession(args: OpenSessionArgs): Promise<OpenSessionResult>;
101
+ bet(args: BetArgs): Promise<TxnResult>;
102
+ win(args: WinArgs): Promise<TxnResult>;
103
+ rollback(args: RollbackArgs): Promise<TxnResult>;
104
+ balance(sessionToken: string): Promise<BalanceResult>;
105
+ settleSession(sessionToken: string): Promise<SettleResult>;
106
+ private txn;
107
+ }
108
+ declare class IAMGameServer {
109
+ readonly ledger: LedgerApi;
110
+ private readonly secretKey;
111
+ private readonly baseUrl;
112
+ private readonly fetchImpl;
113
+ constructor(options: IAMGameServerOptions);
114
+ /**
115
+ * Verify a player's wallet session token server-to-server and return the canonical
116
+ * verified identity (scoped to this key's app + environment). Call this from your
117
+ * backend with the token your frontend received from the wallet, then mint your own
118
+ * app JWT for the returned user. Throws if the session is invalid or scoped elsewhere.
119
+ */
120
+ verifySession(sessionToken: string): Promise<ISessionVerification>;
121
+ private call;
122
+ }
123
+
124
+ declare class IAMGameServerError extends Error {
125
+ readonly code: IAMGameErrorCode | "client/network" | "client/bad_response";
126
+ readonly httpStatus: number;
127
+ readonly details?: Record<string, unknown>;
128
+ constructor(args: {
129
+ code: IAMGameServerError["code"];
130
+ message: string;
131
+ httpStatus: number;
132
+ details?: Record<string, unknown>;
133
+ });
134
+ static fromEnvelope(httpStatus: number, env: IIAMGameErrorEnvelope): IAMGameServerError;
135
+ }
136
+
137
+ export { type BalanceResult, type BetArgs, IAMGameServer as IAMGameWalletServer, type IAMGameServerOptions as IAMGameWalletServerOptions, type ISessionVerification, type OpenSessionArgs, type OpenSessionResult, type RollbackArgs, type SettleResult, type TxnResult, IAMGameServerError as WalletServerError, type WinArgs };
@@ -0,0 +1,137 @@
1
+ type AuthMethod = "siws" | "telegram";
2
+ interface IUserIdentity {
3
+ id: string;
4
+ type: AuthMethod;
5
+ /** For SIWS: base58 Solana pubkey. For Telegram: numeric user id as string. */
6
+ externalId: string;
7
+ }
8
+ interface IUserWallet {
9
+ /** base58 Solana pubkey */
10
+ address: string;
11
+ /** test (devnet) or live (mainnet) — wallets are isolated per environment. */
12
+ environment: "test" | "live";
13
+ custody: "self" | "operator";
14
+ status: "active" | "exported" | "archived";
15
+ }
16
+ /**
17
+ * Result of a server-to-server session verification (POST /v1/sessions/verify).
18
+ * A relying party (game backend) presents a player's wallet session token together
19
+ * with its own secret key; the wallet confirms the session, scopes it to the caller's
20
+ * app + environment, and returns the canonical user identity. The relying party then
21
+ * mints its OWN app JWT for its UI, trusting this verified identity.
22
+ */
23
+ interface ISessionVerification {
24
+ userId: string;
25
+ appId: string;
26
+ environment: "test" | "live";
27
+ authMethod: AuthMethod;
28
+ /** Primary active wallet address for this user, or null if none provisioned yet. */
29
+ walletAddress: string | null;
30
+ wallets: IUserWallet[];
31
+ identities: IUserIdentity[];
32
+ }
33
+
34
+ type IAMGameErrorCode = "auth/invalid_signature" | "auth/challenge_expired" | "auth/challenge_already_redeemed" | "auth/invalid_init_data" | "auth/init_data_stale" | "auth/init_data_replayed" | "auth/missing_token" | "auth/invalid_token" | "auth/expired_token" | "wallet/not_found" | "wallet/insufficient_balance" | "wallet/export_blocked" | "wallet/already_exported" | "user/not_found" | "user/suspended" | "compliance/blocked" | "sign/invalid_transaction" | "sign/wallet_archived" | "sign/internal_failure" | "withdrawal/insufficient_balance" | "withdrawal/limit_exceeded" | "ledger/insufficient_balance" | "ledger/session_not_found" | "ledger/session_closed" | "ledger/bet_not_found" | "ledger/bet_rolled_back" | "ledger/currency_mismatch" | "ratelimit/exceeded" | "idempotency/key_in_use" | "validation/bad_request" | "server/internal";
35
+ interface IIAMGameErrorEnvelope {
36
+ code: IAMGameErrorCode;
37
+ message: string;
38
+ details?: Record<string, unknown>;
39
+ }
40
+
41
+ interface IAMGameServerOptions {
42
+ /** Secret key, e.g. "sk_live_..." or "sk_test_...". */
43
+ secretKey: string;
44
+ /** Base URL incl. version path, e.g. "https://api-wallet.iamgame.com/v1". */
45
+ baseUrl: string;
46
+ fetchImpl?: typeof fetch;
47
+ }
48
+ interface OpenSessionArgs {
49
+ userId: string;
50
+ gameCode: string;
51
+ currency: string;
52
+ lockAmount: bigint;
53
+ }
54
+ interface OpenSessionResult {
55
+ sessionToken: string;
56
+ sessionId: string;
57
+ currency: string;
58
+ lockedBalance: bigint;
59
+ balance: bigint;
60
+ }
61
+ interface BetArgs {
62
+ sessionToken: string;
63
+ transactionUuid: string;
64
+ amount: bigint;
65
+ round?: string;
66
+ roundClosed?: boolean;
67
+ }
68
+ interface WinArgs {
69
+ sessionToken: string;
70
+ transactionUuid: string;
71
+ referenceTransactionUuid: string;
72
+ amount: bigint;
73
+ round?: string;
74
+ roundClosed?: boolean;
75
+ }
76
+ interface RollbackArgs {
77
+ sessionToken: string;
78
+ referenceTransactionUuid: string;
79
+ round?: string;
80
+ }
81
+ interface TxnResult {
82
+ transactionUuid: string;
83
+ balance: bigint;
84
+ currency: string;
85
+ applied: boolean;
86
+ }
87
+ interface BalanceResult {
88
+ balance: bigint;
89
+ currency: string;
90
+ }
91
+ interface SettleResult {
92
+ sessionId: string;
93
+ currency: string;
94
+ payout: bigint;
95
+ railRef: string | null;
96
+ }
97
+ declare class LedgerApi {
98
+ private readonly call;
99
+ constructor(call: <T>(path: string, body: unknown) => Promise<T>);
100
+ openSession(args: OpenSessionArgs): Promise<OpenSessionResult>;
101
+ bet(args: BetArgs): Promise<TxnResult>;
102
+ win(args: WinArgs): Promise<TxnResult>;
103
+ rollback(args: RollbackArgs): Promise<TxnResult>;
104
+ balance(sessionToken: string): Promise<BalanceResult>;
105
+ settleSession(sessionToken: string): Promise<SettleResult>;
106
+ private txn;
107
+ }
108
+ declare class IAMGameServer {
109
+ readonly ledger: LedgerApi;
110
+ private readonly secretKey;
111
+ private readonly baseUrl;
112
+ private readonly fetchImpl;
113
+ constructor(options: IAMGameServerOptions);
114
+ /**
115
+ * Verify a player's wallet session token server-to-server and return the canonical
116
+ * verified identity (scoped to this key's app + environment). Call this from your
117
+ * backend with the token your frontend received from the wallet, then mint your own
118
+ * app JWT for the returned user. Throws if the session is invalid or scoped elsewhere.
119
+ */
120
+ verifySession(sessionToken: string): Promise<ISessionVerification>;
121
+ private call;
122
+ }
123
+
124
+ declare class IAMGameServerError extends Error {
125
+ readonly code: IAMGameErrorCode | "client/network" | "client/bad_response";
126
+ readonly httpStatus: number;
127
+ readonly details?: Record<string, unknown>;
128
+ constructor(args: {
129
+ code: IAMGameServerError["code"];
130
+ message: string;
131
+ httpStatus: number;
132
+ details?: Record<string, unknown>;
133
+ });
134
+ static fromEnvelope(httpStatus: number, env: IIAMGameErrorEnvelope): IAMGameServerError;
135
+ }
136
+
137
+ export { type BalanceResult, type BetArgs, IAMGameServer as IAMGameWalletServer, type IAMGameServerOptions as IAMGameWalletServerOptions, type ISessionVerification, type OpenSessionArgs, type OpenSessionResult, type RollbackArgs, type SettleResult, type TxnResult, IAMGameServerError as WalletServerError, type WinArgs };
package/dist/index.js ADDED
@@ -0,0 +1,148 @@
1
+ // ../../solven/sdk-server/src/errors.ts
2
+ var SolvenServerError = class _SolvenServerError extends Error {
3
+ constructor(args) {
4
+ super(args.message);
5
+ this.name = "SolvenServerError";
6
+ this.code = args.code;
7
+ this.httpStatus = args.httpStatus;
8
+ this.details = args.details;
9
+ }
10
+ static fromEnvelope(httpStatus, env) {
11
+ return new _SolvenServerError({
12
+ code: env.code,
13
+ message: env.message,
14
+ httpStatus,
15
+ details: env.details
16
+ });
17
+ }
18
+ };
19
+
20
+ // ../../solven/sdk-server/src/client.ts
21
+ var LedgerApi = class {
22
+ constructor(call) {
23
+ this.call = call;
24
+ }
25
+ async openSession(args) {
26
+ const r = await this.call("/ledger/sessions", {
27
+ userId: args.userId,
28
+ gameCode: args.gameCode,
29
+ currency: args.currency,
30
+ lockAmount: args.lockAmount.toString()
31
+ });
32
+ return {
33
+ sessionToken: r.sessionToken,
34
+ sessionId: r.sessionId,
35
+ currency: r.currency,
36
+ lockedBalance: BigInt(r.lockedBalance),
37
+ balance: BigInt(r.balance)
38
+ };
39
+ }
40
+ async bet(args) {
41
+ return this.txn("/ledger/bet", {
42
+ sessionToken: args.sessionToken,
43
+ transactionUuid: args.transactionUuid,
44
+ amount: args.amount.toString(),
45
+ round: args.round,
46
+ roundClosed: args.roundClosed
47
+ });
48
+ }
49
+ async win(args) {
50
+ return this.txn("/ledger/win", {
51
+ sessionToken: args.sessionToken,
52
+ transactionUuid: args.transactionUuid,
53
+ referenceTransactionUuid: args.referenceTransactionUuid,
54
+ amount: args.amount.toString(),
55
+ round: args.round,
56
+ roundClosed: args.roundClosed
57
+ });
58
+ }
59
+ async rollback(args) {
60
+ return this.txn("/ledger/rollback", {
61
+ sessionToken: args.sessionToken,
62
+ referenceTransactionUuid: args.referenceTransactionUuid,
63
+ round: args.round
64
+ });
65
+ }
66
+ async balance(sessionToken) {
67
+ const r = await this.call("/ledger/balance", { sessionToken });
68
+ return { balance: BigInt(r.balance), currency: r.currency };
69
+ }
70
+ async settleSession(sessionToken) {
71
+ const r = await this.call(
72
+ "/ledger/settle",
73
+ { sessionToken }
74
+ );
75
+ return { sessionId: r.sessionId, currency: r.currency, payout: BigInt(r.payout), railRef: r.railRef };
76
+ }
77
+ async txn(path, body) {
78
+ const r = await this.call(
79
+ path,
80
+ body
81
+ );
82
+ return { transactionUuid: r.transactionUuid, balance: BigInt(r.balance), currency: r.currency, applied: r.applied };
83
+ }
84
+ };
85
+ var SolvenServer = class {
86
+ constructor(options) {
87
+ if (!options.secretKey.startsWith("sk_")) {
88
+ throw new Error("SolvenServer requires a secret key (sk_...)");
89
+ }
90
+ this.secretKey = options.secretKey;
91
+ this.baseUrl = options.baseUrl.replace(/\/$/, "");
92
+ this.fetchImpl = options.fetchImpl ?? globalThis.fetch.bind(globalThis);
93
+ this.ledger = new LedgerApi((path, body) => this.call(path, body));
94
+ }
95
+ /**
96
+ * Verify a player's wallet session token server-to-server and return the canonical
97
+ * verified identity (scoped to this key's app + environment). Call this from your
98
+ * backend with the token your frontend received from the wallet, then mint your own
99
+ * app JWT for the returned user. Throws if the session is invalid or scoped elsewhere.
100
+ */
101
+ async verifySession(sessionToken) {
102
+ return this.call("/sessions/verify", { sessionToken });
103
+ }
104
+ async call(path, body) {
105
+ let resp;
106
+ try {
107
+ resp = await this.fetchImpl(`${this.baseUrl}${path}`, {
108
+ method: "POST",
109
+ headers: {
110
+ authorization: `Bearer ${this.secretKey}`,
111
+ "content-type": "application/json"
112
+ },
113
+ body: JSON.stringify(body ?? {})
114
+ });
115
+ } catch (err) {
116
+ throw new SolvenServerError({
117
+ code: "client/network",
118
+ message: err instanceof Error ? err.message : "network error",
119
+ httpStatus: 0
120
+ });
121
+ }
122
+ const text = await resp.text();
123
+ let json = void 0;
124
+ if (text) {
125
+ try {
126
+ json = JSON.parse(text);
127
+ } catch {
128
+ throw new SolvenServerError({
129
+ code: "client/bad_response",
130
+ message: `non-JSON response (${resp.status})`,
131
+ httpStatus: resp.status
132
+ });
133
+ }
134
+ }
135
+ if (!resp.ok) {
136
+ const env = json?.error;
137
+ if (env?.code) throw SolvenServerError.fromEnvelope(resp.status, env);
138
+ throw new SolvenServerError({
139
+ code: "client/bad_response",
140
+ message: `request failed (${resp.status})`,
141
+ httpStatus: resp.status
142
+ });
143
+ }
144
+ return json;
145
+ }
146
+ };
147
+
148
+ export { SolvenServer as IAMGameWalletServer, SolvenServerError as WalletServerError };
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@iamgame/wallet-sdk-server",
3
+ "version": "0.1.0",
4
+ "description": "IAMGame Wallet backend SDK — secret-key server-to-server client: verify wallet sessions and run the high-frequency money ledger.",
5
+ "license": "MIT",
6
+ "homepage": "https://wallet.iamgame.com",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/iamgame777/iamgame-mono.git",
10
+ "directory": "iamgame-wallet/sdk-server"
11
+ },
12
+ "keywords": [
13
+ "iamgame",
14
+ "wallet",
15
+ "solana",
16
+ "ledger",
17
+ "server",
18
+ "backend",
19
+ "web3"
20
+ ],
21
+ "type": "module",
22
+ "main": "dist/index.cjs",
23
+ "module": "dist/index.js",
24
+ "types": "dist/index.d.ts",
25
+ "exports": {
26
+ ".": {
27
+ "import": {
28
+ "types": "./dist/index.d.ts",
29
+ "default": "./dist/index.js"
30
+ },
31
+ "require": {
32
+ "types": "./dist/index.d.cts",
33
+ "default": "./dist/index.cjs"
34
+ }
35
+ }
36
+ },
37
+ "files": [
38
+ "dist",
39
+ "README.md"
40
+ ],
41
+ "publishConfig": {
42
+ "access": "public"
43
+ },
44
+ "sideEffects": false,
45
+ "scripts": {
46
+ "build": "tsup && node ../scripts/debrand-dts.mjs",
47
+ "watch": "tsup --watch",
48
+ "prepublishOnly": "npm run build"
49
+ },
50
+ "devDependencies": {
51
+ "@solven/sdk-server": "*",
52
+ "@solven/types": "*",
53
+ "tsup": "^8.3.5",
54
+ "typescript": "^5"
55
+ }
56
+ }