@dimcool/sdk 0.1.24 → 0.1.27

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 CHANGED
@@ -935,16 +935,23 @@ The wallet module provides functionality for managing Solana wallets, checking b
935
935
 
936
936
  ### WalletSigner Interface
937
937
 
938
- The SDK exposes a `WalletSigner` interface for transaction and message signing:
938
+ The SDK exposes a `WalletSigner` interface for transaction and message signing. A signer provides exactly one of `signTransaction` or `signAndSendTransaction`:
939
939
 
940
940
  ```typescript
941
941
  interface WalletSigner {
942
+ address?: string;
942
943
  signMessage: (message: string) => Promise<Uint8Array | string>;
943
- signTransaction: (transaction: Transaction) => Promise<Transaction>;
944
+ signTransaction?: (transaction: Transaction) => Promise<Transaction>;
945
+ signAndSendTransaction?: (transaction: Transaction) => Promise<string>;
944
946
  }
945
947
  ```
946
948
 
947
- This allows the SDK to remain agnostic about how signing is implemented - you can use Phantom wallet for browser apps, or a Keypair for bot applications.
949
+ **Two signing modes:**
950
+
951
+ - **`signTransaction`** (server-sent) — the signer returns signed bytes; the server submits the transaction to the network. Used by `@dimcool/wallet` (keypair agents) and Phantom browser extensions.
952
+ - **`signAndSendTransaction`** (client-sent) — the signer signs AND submits the transaction, returning the signature. The SDK then calls a `confirm-signature` endpoint so the backend can track and confirm it via the queue. Used by Phantom embedded wallets (Google/Apple login).
953
+
954
+ The SDK detects the mode via `sdk.wallet.isSignAndSendMode()` and automatically routes `send()` and `depositForLobby()` through the correct path.
948
955
 
949
956
  If you're building agents, you can use `@dimcool/wallet` and pass `wallet.getSigner()` directly:
950
957
 
@@ -964,12 +971,9 @@ sdk.wallet.setSigner(wallet.getSigner());
964
971
  Configure the wallet signer. This must be called before any signing operations.
965
972
 
966
973
  ```typescript
967
- // Example: Using Phantom wallet (in apps/web)
968
- import { useSolana } from '@phantom/react-sdk';
969
-
970
- const { solana } = useSolana();
971
-
974
+ // Example: Phantom extension (signTransaction — server submits)
972
975
  sdk.wallet.setSigner({
976
+ address: connectedAddress,
973
977
  signMessage: async (message: string) => {
974
978
  return solana.signMessage(new TextEncoder().encode(message));
975
979
  },
@@ -980,13 +984,28 @@ sdk.wallet.setSigner({
980
984
  ```
981
985
 
982
986
  ```typescript
983
- // Example: Using a Keypair (for bots/Node.js)
987
+ // Example: Phantom embedded / Google/Apple (signAndSendTransaction — client submits)
988
+ sdk.wallet.setSigner({
989
+ address: connectedAddress,
990
+ signMessage: async (message: string) => {
991
+ return solana.signMessage(new TextEncoder().encode(message));
992
+ },
993
+ signAndSendTransaction: async (transaction: Transaction) => {
994
+ const result = await solana.signAndSendTransaction(transaction);
995
+ return typeof result === 'string' ? result : result.signature;
996
+ },
997
+ });
998
+ ```
999
+
1000
+ ```typescript
1001
+ // Example: Using a Keypair (for bots/Node.js — signTransaction)
984
1002
  import { Keypair } from '@solana/web3.js';
985
1003
  import * as nacl from 'tweetnacl';
986
1004
 
987
1005
  const keypair = Keypair.fromSecretKey(/* ... */);
988
1006
 
989
1007
  sdk.wallet.setSigner({
1008
+ address: keypair.publicKey.toBase58(),
990
1009
  signMessage: async (message: string) => {
991
1010
  const messageBytes = new TextEncoder().encode(message);
992
1011
  return nacl.sign.detached(messageBytes, keypair.secretKey);
@@ -1080,40 +1099,37 @@ const signature = await sdk.wallet.signMessage('Hello, world!');
1080
1099
 
1081
1100
  ### `signTransaction(transaction: Transaction): Promise<Transaction>`
1082
1101
 
1083
- Sign a Solana transaction using the configured signer.
1102
+ Sign a Solana transaction using the configured signer. Only available when the signer provides `signTransaction`.
1084
1103
 
1085
1104
  ```typescript
1086
- import { Transaction } from '@solana/web3.js';
1087
-
1088
- const unsignedTransaction = Transaction.from(/* ... */);
1089
1105
  const signedTransaction = await sdk.wallet.signTransaction(unsignedTransaction);
1090
1106
  ```
1091
1107
 
1092
- **Parameters:**
1108
+ **Throws** if the signer does not support `signTransaction` (i.e., it only has `signAndSendTransaction`).
1093
1109
 
1094
- - `transaction: Transaction` - The unsigned Solana transaction to sign
1110
+ ### `signAndSendTransaction(transaction: Transaction): Promise<string>`
1095
1111
 
1096
- **Returns:**
1112
+ Sign and send a Solana transaction in one step. Only available when the signer provides `signAndSendTransaction`. Returns the transaction signature.
1097
1113
 
1098
- - `Promise<Transaction>` - The signed transaction
1114
+ ```typescript
1115
+ const signature = await sdk.wallet.signAndSendTransaction(unsignedTransaction);
1116
+ ```
1099
1117
 
1100
- **Example:**
1118
+ **Throws** if the signer does not support `signAndSendTransaction`.
1101
1119
 
1102
- ```typescript
1103
- // Transaction should be prepared by the backend first
1104
- const { unsignedTransaction } = await sdk.http.post(
1105
- '/transactions/prepare-deposit',
1106
- {
1107
- lobbyId: 'lobby-id',
1108
- amount: 100,
1109
- },
1110
- );
1120
+ ### `isSignAndSendMode(): boolean`
1111
1121
 
1112
- const tx = Transaction.from(Buffer.from(unsignedTransaction, 'base64'));
1113
- const signedTx = await sdk.wallet.signTransaction(tx);
1122
+ Check which signing mode the current signer uses.
1123
+
1124
+ ```typescript
1125
+ if (sdk.wallet.isSignAndSendMode()) {
1126
+ // Client-sent path: signer signs AND sends
1127
+ } else {
1128
+ // Server-sent path: signer returns signed bytes
1129
+ }
1114
1130
  ```
1115
1131
 
1116
- **Note:** A signer must be configured first using `setSigner()`.
1132
+ **Note:** `send()` and `depositForLobby()` use this internally to route automatically.
1117
1133
 
1118
1134
  ### `send(recipient, amount, token?)`
1119
1135
 
@@ -1187,7 +1203,23 @@ Use these only when you explicitly need manual control of signing/submission.
1187
1203
 
1188
1204
  ## Escrow Module (`sdk.escrow`)
1189
1205
 
1190
- The escrow module provides functionality for managing deposits, checking deposit status, and handling the escrow flow for game lobbies. This module works in conjunction with the wallet module to enable secure, blockchain-based deposits.
1206
+ The escrow module provides functionality for managing deposits, checking deposit status, and handling the escrow flow for game lobbies. It is constructed with `http` and `wallet` (the wallet is used for signing in `depositForLobby`). Use the wallet module to set a signer via `sdk.wallet.setSigner(...)` before calling `depositForLobby`.
1207
+
1208
+ ### One-call lobby deposit
1209
+
1210
+ For the common case of depositing into a paid lobby in one step, use **`depositForLobby(lobbyId: string): Promise<DepositForLobbyResponse>`**. It starts deposits, prepares the transaction, signs with the configured wallet, submits, and polls until the current user's deposit is confirmed (or all deposits are confirmed for multi-player). Requires a signer to be set (`sdk.wallet.setSigner(...)`).
1211
+
1212
+ ```typescript
1213
+ const result = await sdk.escrow.depositForLobby(lobbyId);
1214
+ // result: { signature: string; status: string; canProceedToQueue: boolean }
1215
+ if (result.canProceedToQueue) {
1216
+ await sdk.lobbies.joinQueue(lobbyId);
1217
+ }
1218
+ ```
1219
+
1220
+ **Response:** `{ signature, status, canProceedToQueue }`. When `canProceedToQueue` is true, call `sdk.lobbies.joinQueue(lobbyId)` to enter matchmaking.
1221
+
1222
+ **Throws:** If no signer is configured: "No signer configured. Use sdk.wallet.setSigner(...) first."
1191
1223
 
1192
1224
  ### `startDeposits(lobbyId: string): Promise<void>`
1193
1225
 
@@ -1255,57 +1287,30 @@ const signedTx = await sdk.wallet.signTransaction(unsignedTx);
1255
1287
 
1256
1288
  **Note:** The transaction amount is automatically set to match the lobby's `betAmount`. The transaction is partially signed by the fee payer (server) and requires the user's signature.
1257
1289
 
1258
- ### `submitDepositAndJoinQueue(lobbyId: string, signedTransaction: string, lobbies: Lobbies): Promise<Lobby>`
1290
+ ### `depositForLobbySync(lobbyId: string): Promise<DepositForLobbyResponse>`
1259
1291
 
1260
- Submit a signed deposit transaction and automatically join the queue when the deposit is confirmed. This is a convenience method that combines deposit submission, confirmation waiting, and queue joining.
1292
+ Zero-polling deposit variant using server-side `awaitConfirmation`. Only 2 HTTP calls total with no client-side polling. Ideal for agents and bots.
1261
1293
 
1262
1294
  ```typescript
1263
- const finalLobby = await sdk.escrow.submitDepositAndJoinQueue(
1264
- lobbyId,
1265
- signedTxBase64,
1266
- sdk.lobbies,
1267
- );
1295
+ const result = await sdk.escrow.depositForLobbySync(lobbyId);
1296
+ // result: { signature: string, status: 'confirmed', canProceedToQueue: true }
1268
1297
  ```
1269
1298
 
1270
1299
  **Parameters:**
1271
1300
 
1272
1301
  - `lobbyId: string` - The lobby ID
1273
- - `signedTransaction: string` - The signed transaction (base64 encoded)
1274
- - `lobbies: Lobbies` - The lobbies service instance (from `sdk.lobbies`)
1275
1302
 
1276
1303
  **Returns:**
1277
1304
 
1278
- - `Promise<Lobby>` - The lobby with updated status (will be 'queued' or 'active' if full)
1305
+ - `Promise<DepositForLobbyResponse>` - The deposit result with confirmed status
1279
1306
 
1280
1307
  **Behavior:**
1281
1308
 
1282
- 1. Submits the signed deposit transaction to the Solana network
1283
- 2. Polls deposit status until all deposits are confirmed (max 30 seconds)
1284
- 3. Automatically joins the matchmaking queue when deposits are confirmed
1285
- 4. Returns the updated lobby
1286
-
1287
- **Example:**
1288
-
1289
- ```typescript
1290
- // After signing the transaction from playAgain()
1291
- const signedTxBase64 = signedTx.serialize().toString('base64');
1292
- const finalLobby = await sdk.escrow.submitDepositAndJoinQueue(
1293
- lobby.id,
1294
- signedTxBase64,
1295
- sdk.lobbies,
1296
- );
1297
-
1298
- // Lobby is now in queue or active if full
1299
- console.log(`Lobby status: ${finalLobby.status}`);
1300
- ```
1301
-
1302
- **Error Handling:**
1303
-
1304
- - Throws an error if deposit confirmation times out (30 seconds)
1305
- - Throws an error if deposit submission fails
1306
- - Throws an error if queue joining fails
1309
+ 1. Calls `prepareAndStartDeposit` to prepare the unsigned transaction (1 HTTP call)
1310
+ 2. Signs the transaction locally and submits with `awaitConfirmation=true` (1 HTTP call)
1311
+ 3. Server waits for on-chain confirmation before returning
1307
1312
 
1308
- **Note:** This method is typically used after `playAgain()` to complete the "Play Again" flow in one call.
1313
+ **Note:** Requires `sdk.wallet.setSigner()` to be configured. The server auto-joins the matchmaking queue when all deposits are confirmed.
1309
1314
 
1310
1315
  ### `submitDeposit(lobbyId: string, signedTransaction: string): Promise<SubmitDepositResponse>`
1311
1316
 
@@ -1708,25 +1713,11 @@ const { lobby, unsignedTransaction } = await sdk.lobbies.playAgain(
1708
1713
  sdk.escrow,
1709
1714
  );
1710
1715
 
1711
- // Decode and sign the transaction
1712
- const binaryString = atob(unsignedTransaction);
1713
- const bytes = new Uint8Array(binaryString.length);
1714
- for (let i = 0; i < binaryString.length; i++) {
1715
- bytes[i] = binaryString.charCodeAt(i);
1716
- }
1717
- const unsignedTx = Transaction.from(bytes);
1718
- const signedTx = await sdk.wallet.signTransaction(unsignedTx);
1719
-
1720
- // Submit deposit and join queue
1721
- const signedTxBase64 = signedTx.serialize().toString('base64');
1722
- const finalLobby = await sdk.escrow.submitDepositAndJoinQueue(
1723
- lobby.id,
1724
- signedTxBase64,
1725
- sdk.lobbies,
1726
- );
1716
+ // Deposit using the sync (server-awaited) variant
1717
+ const result = await sdk.escrow.depositForLobbySync(lobby.id);
1727
1718
  ```
1728
1719
 
1729
- **Note:** After signing the transaction, use `submitDepositAndJoinQueue()` to complete the flow and automatically join the matchmaking queue.
1720
+ **Note:** After `playAgain()`, use `depositForLobbySync()` (for agents) or `depositForLobby()` (for React hooks) to complete the deposit flow. The server auto-joins the matchmaking queue when all deposits are confirmed.
1730
1721
 
1731
1722
  ### Admin Methods
1732
1723