@1upmonster/duel 0.1.8 → 0.2.2

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.
Files changed (186) hide show
  1. package/README.md +110 -59
  2. package/dist/admin.d.ts +25 -40
  3. package/dist/admin.js +93 -114
  4. package/dist/encryption.js +1 -2
  5. package/dist/generated/duel/accounts/index.d.ts +10 -0
  6. package/dist/generated/duel/accounts/index.js +11 -0
  7. package/dist/generated/duel/accounts/matchTicket.d.ts +38 -0
  8. package/dist/generated/duel/accounts/matchTicket.js +45 -0
  9. package/dist/generated/duel/accounts/queue.d.ts +42 -0
  10. package/dist/generated/duel/accounts/queue.js +45 -0
  11. package/dist/generated/duel/accounts/tenant.d.ts +41 -0
  12. package/dist/generated/duel/accounts/tenant.js +44 -0
  13. package/dist/generated/duel/errors/duel.d.ts +31 -0
  14. package/dist/generated/duel/errors/duel.js +35 -0
  15. package/dist/generated/duel/errors/index.d.ts +8 -0
  16. package/dist/generated/duel/errors/index.js +9 -0
  17. package/dist/generated/duel/index.d.ts +12 -0
  18. package/dist/generated/duel/index.js +13 -0
  19. package/dist/generated/duel/instructions/cancelTicket.d.ts +45 -0
  20. package/dist/generated/duel/instructions/cancelTicket.js +56 -0
  21. package/dist/generated/duel/instructions/closeTicket.d.ts +45 -0
  22. package/dist/generated/duel/instructions/closeTicket.js +56 -0
  23. package/dist/generated/duel/instructions/commitTickets.d.ts +39 -0
  24. package/dist/generated/duel/instructions/commitTickets.js +50 -0
  25. package/dist/generated/duel/instructions/createTicket.d.ts +48 -0
  26. package/dist/generated/duel/instructions/createTicket.js +63 -0
  27. package/dist/generated/duel/instructions/delegateQueue.d.ts +69 -0
  28. package/dist/generated/duel/instructions/delegateQueue.js +90 -0
  29. package/dist/generated/duel/instructions/delegateTicket.d.ts +69 -0
  30. package/dist/generated/duel/instructions/delegateTicket.js +90 -0
  31. package/dist/generated/duel/instructions/flushMatches.d.ts +37 -0
  32. package/dist/generated/duel/instructions/flushMatches.js +43 -0
  33. package/dist/generated/duel/instructions/index.d.ts +19 -0
  34. package/dist/generated/duel/instructions/index.js +20 -0
  35. package/dist/generated/duel/instructions/initializeQueue.d.ts +48 -0
  36. package/dist/generated/duel/instructions/initializeQueue.js +63 -0
  37. package/dist/generated/duel/instructions/initializeTenant.d.ts +70 -0
  38. package/dist/generated/duel/instructions/initializeTenant.js +67 -0
  39. package/dist/generated/duel/instructions/joinQueue.d.ts +51 -0
  40. package/dist/generated/duel/instructions/joinQueue.js +56 -0
  41. package/dist/generated/duel/instructions/processUndelegation.d.ts +43 -0
  42. package/dist/generated/duel/instructions/processUndelegation.js +49 -0
  43. package/dist/generated/duel/instructions/setupTicketPermission.d.ts +54 -0
  44. package/dist/generated/duel/instructions/setupTicketPermission.js +63 -0
  45. package/dist/generated/duel/programs/duel.d.ts +92 -0
  46. package/dist/generated/duel/programs/duel.js +146 -0
  47. package/dist/generated/duel/programs/index.d.ts +8 -0
  48. package/dist/generated/duel/programs/index.js +9 -0
  49. package/dist/generated/duel/types/accountType.d.ts +25 -0
  50. package/dist/generated/duel/types/accountType.js +25 -0
  51. package/dist/generated/duel/types/index.d.ts +13 -0
  52. package/dist/generated/duel/types/index.js +14 -0
  53. package/dist/generated/duel/types/matchEntry.d.ts +23 -0
  54. package/dist/generated/duel/types/matchEntry.js +18 -0
  55. package/dist/generated/duel/types/matchFound.d.ts +23 -0
  56. package/dist/generated/duel/types/matchFound.js +18 -0
  57. package/dist/generated/duel/types/pendingMatch.d.ts +21 -0
  58. package/dist/generated/duel/types/pendingMatch.js +18 -0
  59. package/dist/generated/duel/types/queueEntry.d.ts +19 -0
  60. package/dist/generated/duel/types/queueEntry.js +18 -0
  61. package/dist/generated/duel/types/ticketStatus.d.ts +40 -0
  62. package/dist/generated/duel/types/ticketStatus.js +25 -0
  63. package/dist/generated/rps-game/accounts/gameSession.d.ts +40 -0
  64. package/dist/generated/rps-game/accounts/gameSession.js +45 -0
  65. package/dist/generated/rps-game/accounts/index.d.ts +9 -0
  66. package/dist/generated/rps-game/accounts/index.js +10 -0
  67. package/dist/generated/rps-game/accounts/playerProfile.d.ts +36 -0
  68. package/dist/generated/rps-game/accounts/playerProfile.js +47 -0
  69. package/dist/generated/rps-game/errors/index.d.ts +8 -0
  70. package/dist/generated/rps-game/errors/index.js +9 -0
  71. package/dist/generated/rps-game/errors/rpsGame.d.ts +25 -0
  72. package/dist/generated/rps-game/errors/rpsGame.js +29 -0
  73. package/dist/generated/rps-game/index.d.ts +12 -0
  74. package/dist/generated/rps-game/index.js +13 -0
  75. package/dist/generated/rps-game/instructions/closePlayer.d.ts +45 -0
  76. package/dist/generated/rps-game/instructions/closePlayer.js +56 -0
  77. package/dist/generated/rps-game/instructions/delegatePda.d.ts +69 -0
  78. package/dist/generated/rps-game/instructions/delegatePda.js +90 -0
  79. package/dist/generated/rps-game/instructions/index.d.ts +16 -0
  80. package/dist/generated/rps-game/instructions/index.js +17 -0
  81. package/dist/generated/rps-game/instructions/initializePlayer.d.ts +48 -0
  82. package/dist/generated/rps-game/instructions/initializePlayer.js +63 -0
  83. package/dist/generated/rps-game/instructions/makeChoice.d.ts +44 -0
  84. package/dist/generated/rps-game/instructions/makeChoice.js +46 -0
  85. package/dist/generated/rps-game/instructions/onMatchFound.d.ts +43 -0
  86. package/dist/generated/rps-game/instructions/onMatchFound.js +45 -0
  87. package/dist/generated/rps-game/instructions/persistResults.d.ts +43 -0
  88. package/dist/generated/rps-game/instructions/persistResults.js +50 -0
  89. package/dist/generated/rps-game/instructions/processUndelegation.d.ts +43 -0
  90. package/dist/generated/rps-game/instructions/processUndelegation.js +49 -0
  91. package/dist/generated/rps-game/instructions/startGame.d.ts +54 -0
  92. package/dist/generated/rps-game/instructions/startGame.js +67 -0
  93. package/dist/generated/rps-game/instructions/startGameWithTicket.d.ts +57 -0
  94. package/dist/generated/rps-game/instructions/startGameWithTicket.js +67 -0
  95. package/dist/generated/rps-game/programs/index.d.ts +8 -0
  96. package/dist/generated/rps-game/programs/index.js +9 -0
  97. package/dist/generated/rps-game/programs/rpsGame.d.ts +78 -0
  98. package/dist/generated/rps-game/programs/rpsGame.js +118 -0
  99. package/dist/generated/rps-game/types/accountType.d.ts +34 -0
  100. package/dist/generated/rps-game/types/accountType.js +25 -0
  101. package/dist/generated/rps-game/types/choice.d.ts +17 -0
  102. package/dist/generated/rps-game/types/choice.js +25 -0
  103. package/dist/generated/rps-game/types/gameResult.d.ts +26 -0
  104. package/dist/generated/rps-game/types/gameResult.js +25 -0
  105. package/dist/generated/rps-game/types/index.d.ts +10 -0
  106. package/dist/generated/rps-game/types/index.js +11 -0
  107. package/dist/index.d.ts +2 -1
  108. package/dist/index.js +3 -2
  109. package/dist/player.d.ts +25 -46
  110. package/dist/player.js +81 -140
  111. package/dist/tee.d.ts +14 -0
  112. package/dist/tee.js +62 -0
  113. package/dist/transaction.d.ts +11 -0
  114. package/dist/transaction.js +50 -0
  115. package/dist/utils.d.ts +4 -4
  116. package/dist/utils.js +23 -8
  117. package/package.json +3 -6
  118. package/src/admin.ts +151 -161
  119. package/src/duel.json +66 -7
  120. package/src/encryption.ts +0 -3
  121. package/src/generated/duel/accounts/index.ts +11 -0
  122. package/src/generated/duel/accounts/matchTicket.ts +77 -0
  123. package/src/generated/duel/accounts/queue.ts +77 -0
  124. package/src/generated/duel/accounts/tenant.ts +76 -0
  125. package/src/generated/duel/errors/duel.ts +46 -0
  126. package/src/generated/duel/errors/index.ts +9 -0
  127. package/src/generated/duel/index.ts +13 -0
  128. package/src/generated/duel/instructions/cancelTicket.ts +100 -0
  129. package/src/generated/duel/instructions/closeTicket.ts +100 -0
  130. package/src/generated/duel/instructions/commitTickets.ts +84 -0
  131. package/src/generated/duel/instructions/createTicket.ts +109 -0
  132. package/src/generated/duel/instructions/delegateQueue.ts +157 -0
  133. package/src/generated/duel/instructions/delegateTicket.ts +157 -0
  134. package/src/generated/duel/instructions/flushMatches.ts +76 -0
  135. package/src/generated/duel/instructions/index.ts +20 -0
  136. package/src/generated/duel/instructions/initializeQueue.ts +109 -0
  137. package/src/generated/duel/instructions/initializeTenant.ts +126 -0
  138. package/src/generated/duel/instructions/joinQueue.ts +106 -0
  139. package/src/generated/duel/instructions/processUndelegation.ts +86 -0
  140. package/src/generated/duel/instructions/setupTicketPermission.ts +115 -0
  141. package/src/generated/duel/programs/duel.ts +108 -0
  142. package/src/generated/duel/programs/index.ts +9 -0
  143. package/src/generated/duel/types/accountType.ts +36 -0
  144. package/src/generated/duel/types/index.ts +14 -0
  145. package/src/generated/duel/types/matchEntry.ts +25 -0
  146. package/src/generated/duel/types/matchFound.ts +25 -0
  147. package/src/generated/duel/types/pendingMatch.ts +25 -0
  148. package/src/generated/duel/types/queueEntry.ts +25 -0
  149. package/src/generated/duel/types/ticketStatus.ts +38 -0
  150. package/src/generated/rps-game/accounts/gameSession.ts +77 -0
  151. package/src/generated/rps-game/accounts/index.ts +10 -0
  152. package/src/generated/rps-game/accounts/playerProfile.ts +80 -0
  153. package/src/generated/rps-game/errors/index.ts +9 -0
  154. package/src/generated/rps-game/errors/rpsGame.ts +40 -0
  155. package/src/generated/rps-game/index.ts +13 -0
  156. package/src/generated/rps-game/instructions/closePlayer.ts +100 -0
  157. package/src/generated/rps-game/instructions/delegatePda.ts +157 -0
  158. package/src/generated/rps-game/instructions/index.ts +17 -0
  159. package/src/generated/rps-game/instructions/initializePlayer.ts +109 -0
  160. package/src/generated/rps-game/instructions/makeChoice.ts +84 -0
  161. package/src/generated/rps-game/instructions/onMatchFound.ts +79 -0
  162. package/src/generated/rps-game/instructions/persistResults.ts +88 -0
  163. package/src/generated/rps-game/instructions/processUndelegation.ts +86 -0
  164. package/src/generated/rps-game/instructions/startGame.ts +118 -0
  165. package/src/generated/rps-game/instructions/startGameWithTicket.ts +121 -0
  166. package/src/generated/rps-game/programs/index.ts +9 -0
  167. package/src/generated/rps-game/programs/rpsGame.ts +95 -0
  168. package/src/generated/rps-game/types/accountType.ts +36 -0
  169. package/src/generated/rps-game/types/choice.ts +25 -0
  170. package/src/generated/rps-game/types/gameResult.ts +37 -0
  171. package/src/generated/rps-game/types/index.ts +11 -0
  172. package/src/index.ts +2 -1
  173. package/src/player.ts +129 -192
  174. package/src/{idl/private_matchmaking.json → rps_game.json} +547 -583
  175. package/src/tee.ts +79 -0
  176. package/src/transaction.ts +90 -0
  177. package/src/utils.ts +35 -20
  178. package/tsconfig.json +2 -2
  179. package/dist/client.d.ts +0 -54
  180. package/dist/client.js +0 -265
  181. package/dist/duel.json +0 -1207
  182. package/dist/private_matchmaking.json +0 -534
  183. package/dist/types.d.ts +0 -635
  184. package/dist/types.js +0 -2
  185. package/src/idl/private_matchmaking.ts +0 -1033
  186. package/src/types.ts +0 -300
package/dist/tee.js ADDED
@@ -0,0 +1,62 @@
1
+ import { getBase58Decoder, createSignableMessage, } from "@solana/kit";
2
+ /**
3
+ * Authenticate with the MagicBlock TEE via challenge-sign flow.
4
+ */
5
+ export async function getAuthToken(rpcUrl, signer) {
6
+ const challengeRes = await fetch(`${rpcUrl}/auth/challenge?pubkey=${signer.address}`);
7
+ if (!challengeRes.ok) {
8
+ throw new Error(`TEE challenge failed: ${challengeRes.statusText}`);
9
+ }
10
+ const { challenge } = (await challengeRes.json());
11
+ const challengeBytes = new TextEncoder().encode(challenge);
12
+ const [sigDict] = await signer.signMessages([createSignableMessage(challengeBytes)]);
13
+ const signature = sigDict[signer.address];
14
+ const signatureString = getBase58Decoder().decode(signature);
15
+ const tokenRes = await fetch(`${rpcUrl}/auth/login`, {
16
+ method: "POST",
17
+ headers: { "Content-Type": "application/json" },
18
+ body: JSON.stringify({
19
+ pubkey: signer.address,
20
+ challenge,
21
+ signature: signatureString,
22
+ }),
23
+ });
24
+ const authJson = (await tokenRes.json());
25
+ if (tokenRes.status !== 200) {
26
+ throw new Error(`Failed to authenticate: ${authJson.error}`);
27
+ }
28
+ const expiresAt = authJson.expiresAt ?? Date.now() + 1000 * 60 * 60 * 24 * 30;
29
+ return { token: authJson.token, expiresAt };
30
+ }
31
+ /**
32
+ * Poll the TEE /permission endpoint until the given PDA has authorized users,
33
+ * indicating delegation is active. Returns false on timeout (does not throw).
34
+ */
35
+ export async function waitUntilPermissionActive(teeUrlWithToken, pda, timeoutMs = 30000) {
36
+ // Parse URL: "https://host/path?token=xxx" -> baseUrl="https://host/path", tokenParam="token=xxx"
37
+ const [baseUrl, tokenParam] = teeUrlWithToken.replace("/?", "?").split("?");
38
+ let permissionUrl;
39
+ if (tokenParam) {
40
+ permissionUrl = `${baseUrl}/permission?${tokenParam}&pubkey=${pda}`;
41
+ }
42
+ else {
43
+ permissionUrl = `${baseUrl}/permission?pubkey=${pda}`;
44
+ }
45
+ const start = Date.now();
46
+ while (Date.now() - start < timeoutMs) {
47
+ try {
48
+ const res = await fetch(permissionUrl);
49
+ if (res.ok) {
50
+ const { authorizedUsers } = (await res.json());
51
+ if (authorizedUsers && authorizedUsers.length > 0)
52
+ return true;
53
+ }
54
+ }
55
+ catch {
56
+ // ignore transient errors, keep polling
57
+ }
58
+ await new Promise((r) => setTimeout(r, 400));
59
+ }
60
+ return false;
61
+ }
62
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3RlZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsZ0JBQWdCLEVBQ2hCLHFCQUFxQixHQUd0QixNQUFNLGFBQWEsQ0FBQztBQUlyQjs7R0FFRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsWUFBWSxDQUNoQyxNQUFjLEVBQ2QsTUFBNEI7SUFFNUIsTUFBTSxZQUFZLEdBQUcsTUFBTSxLQUFLLENBQzlCLEdBQUcsTUFBTSwwQkFBMEIsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUNwRCxDQUFDO0lBQ0YsSUFBSSxDQUFDLFlBQVksQ0FBQyxFQUFFLEVBQUUsQ0FBQztRQUNyQixNQUFNLElBQUksS0FBSyxDQUFDLHlCQUF5QixZQUFZLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQztJQUN0RSxDQUFDO0lBQ0QsTUFBTSxFQUFFLFNBQVMsRUFBRSxHQUFHLENBQUMsTUFBTSxZQUFZLENBQUMsSUFBSSxFQUFFLENBQTBCLENBQUM7SUFFM0UsTUFBTSxjQUFjLEdBQUcsSUFBSSxXQUFXLEVBQUUsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDM0QsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLE1BQU0sTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDLHFCQUFxQixDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNyRixNQUFNLFNBQVMsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLE9BQWtCLENBQUMsQ0FBQztJQUNyRCxNQUFNLGVBQWUsR0FBRyxnQkFBZ0IsRUFBRSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUU3RCxNQUFNLFFBQVEsR0FBRyxNQUFNLEtBQUssQ0FBQyxHQUFHLE1BQU0sYUFBYSxFQUFFO1FBQ25ELE1BQU0sRUFBRSxNQUFNO1FBQ2QsT0FBTyxFQUFFLEVBQUUsY0FBYyxFQUFFLGtCQUFrQixFQUFFO1FBQy9DLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDO1lBQ25CLE1BQU0sRUFBRSxNQUFNLENBQUMsT0FBTztZQUN0QixTQUFTO1lBQ1QsU0FBUyxFQUFFLGVBQWU7U0FDM0IsQ0FBQztLQUNILENBQUMsQ0FBQztJQUNILE1BQU0sUUFBUSxHQUFHLENBQUMsTUFBTSxRQUFRLENBQUMsSUFBSSxFQUFFLENBQTBELENBQUM7SUFDbEcsSUFBSSxRQUFRLENBQUMsTUFBTSxLQUFLLEdBQUcsRUFBRSxDQUFDO1FBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsMkJBQTJCLFFBQVEsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDO0lBQy9ELENBQUM7SUFDRCxNQUFNLFNBQVMsR0FBRyxRQUFRLENBQUMsU0FBUyxJQUFJLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxJQUFJLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxDQUFDO0lBQzlFLE9BQU8sRUFBRSxLQUFLLEVBQUUsUUFBUSxDQUFDLEtBQUssRUFBRSxTQUFTLEVBQUUsQ0FBQztBQUM5QyxDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSx5QkFBeUIsQ0FDN0MsZUFBdUIsRUFDdkIsR0FBWSxFQUNaLFNBQVMsR0FBRyxLQUFLO0lBRWpCLGtHQUFrRztJQUNsRyxNQUFNLENBQUMsT0FBTyxFQUFFLFVBQVUsQ0FBQyxHQUFHLGVBQWUsQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUM1RSxJQUFJLGFBQXFCLENBQUM7SUFDMUIsSUFBSSxVQUFVLEVBQUUsQ0FBQztRQUNmLGFBQWEsR0FBRyxHQUFHLE9BQU8sZUFBZSxVQUFVLFdBQVcsR0FBRyxFQUFFLENBQUM7SUFDdEUsQ0FBQztTQUFNLENBQUM7UUFDTixhQUFhLEdBQUcsR0FBRyxPQUFPLHNCQUFzQixHQUFHLEVBQUUsQ0FBQztJQUN4RCxDQUFDO0lBRUQsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBQ3pCLE9BQU8sSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLEtBQUssR0FBRyxTQUFTLEVBQUUsQ0FBQztRQUN0QyxJQUFJLENBQUM7WUFDSCxNQUFNLEdBQUcsR0FBRyxNQUFNLEtBQUssQ0FBQyxhQUFhLENBQUMsQ0FBQztZQUN2QyxJQUFJLEdBQUcsQ0FBQyxFQUFFLEVBQUUsQ0FBQztnQkFDWCxNQUFNLEVBQUUsZUFBZSxFQUFFLEdBQUcsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxJQUFJLEVBQUUsQ0FBb0MsQ0FBQztnQkFDbEYsSUFBSSxlQUFlLElBQUksZUFBZSxDQUFDLE1BQU0sR0FBRyxDQUFDO29CQUFFLE9BQU8sSUFBSSxDQUFDO1lBQ2pFLENBQUM7UUFDSCxDQUFDO1FBQUMsTUFBTSxDQUFDO1lBQ1Asd0NBQXdDO1FBQzFDLENBQUM7UUFDRCxNQUFNLElBQUksT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxVQUFVLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDL0MsQ0FBQztJQUNELE9BQU8sS0FBSyxDQUFDO0FBQ2YsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIGdldEJhc2U1OERlY29kZXIsXG4gIGNyZWF0ZVNpZ25hYmxlTWVzc2FnZSxcbiAgdHlwZSBBZGRyZXNzLFxuICB0eXBlIE1lc3NhZ2VQYXJ0aWFsU2lnbmVyLFxufSBmcm9tIFwiQHNvbGFuYS9raXRcIjtcblxuZXhwb3J0IHR5cGUgeyBNZXNzYWdlUGFydGlhbFNpZ25lciBhcyBNZXNzYWdlU2lnbmVyIH07XG5cbi8qKlxuICogQXV0aGVudGljYXRlIHdpdGggdGhlIE1hZ2ljQmxvY2sgVEVFIHZpYSBjaGFsbGVuZ2Utc2lnbiBmbG93LlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0QXV0aFRva2VuKFxuICBycGNVcmw6IHN0cmluZyxcbiAgc2lnbmVyOiBNZXNzYWdlUGFydGlhbFNpZ25lcixcbik6IFByb21pc2U8eyB0b2tlbjogc3RyaW5nOyBleHBpcmVzQXQ6IG51bWJlciB9PiB7XG4gIGNvbnN0IGNoYWxsZW5nZVJlcyA9IGF3YWl0IGZldGNoKFxuICAgIGAke3JwY1VybH0vYXV0aC9jaGFsbGVuZ2U/cHVia2V5PSR7c2lnbmVyLmFkZHJlc3N9YFxuICApO1xuICBpZiAoIWNoYWxsZW5nZVJlcy5vaykge1xuICAgIHRocm93IG5ldyBFcnJvcihgVEVFIGNoYWxsZW5nZSBmYWlsZWQ6ICR7Y2hhbGxlbmdlUmVzLnN0YXR1c1RleHR9YCk7XG4gIH1cbiAgY29uc3QgeyBjaGFsbGVuZ2UgfSA9IChhd2FpdCBjaGFsbGVuZ2VSZXMuanNvbigpKSBhcyB7IGNoYWxsZW5nZTogc3RyaW5nIH07XG5cbiAgY29uc3QgY2hhbGxlbmdlQnl0ZXMgPSBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUoY2hhbGxlbmdlKTtcbiAgY29uc3QgW3NpZ0RpY3RdID0gYXdhaXQgc2lnbmVyLnNpZ25NZXNzYWdlcyhbY3JlYXRlU2lnbmFibGVNZXNzYWdlKGNoYWxsZW5nZUJ5dGVzKV0pO1xuICBjb25zdCBzaWduYXR1cmUgPSBzaWdEaWN0W3NpZ25lci5hZGRyZXNzIGFzIEFkZHJlc3NdO1xuICBjb25zdCBzaWduYXR1cmVTdHJpbmcgPSBnZXRCYXNlNThEZWNvZGVyKCkuZGVjb2RlKHNpZ25hdHVyZSk7XG5cbiAgY29uc3QgdG9rZW5SZXMgPSBhd2FpdCBmZXRjaChgJHtycGNVcmx9L2F1dGgvbG9naW5gLCB7XG4gICAgbWV0aG9kOiBcIlBPU1RcIixcbiAgICBoZWFkZXJzOiB7IFwiQ29udGVudC1UeXBlXCI6IFwiYXBwbGljYXRpb24vanNvblwiIH0sXG4gICAgYm9keTogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgcHVia2V5OiBzaWduZXIuYWRkcmVzcyxcbiAgICAgIGNoYWxsZW5nZSxcbiAgICAgIHNpZ25hdHVyZTogc2lnbmF0dXJlU3RyaW5nLFxuICAgIH0pLFxuICB9KTtcbiAgY29uc3QgYXV0aEpzb24gPSAoYXdhaXQgdG9rZW5SZXMuanNvbigpKSBhcyB7IHRva2VuOiBzdHJpbmc7IGV4cGlyZXNBdD86IG51bWJlcjsgZXJyb3I/OiBzdHJpbmcgfTtcbiAgaWYgKHRva2VuUmVzLnN0YXR1cyAhPT0gMjAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gYXV0aGVudGljYXRlOiAke2F1dGhKc29uLmVycm9yfWApO1xuICB9XG4gIGNvbnN0IGV4cGlyZXNBdCA9IGF1dGhKc29uLmV4cGlyZXNBdCA/PyBEYXRlLm5vdygpICsgMTAwMCAqIDYwICogNjAgKiAyNCAqIDMwO1xuICByZXR1cm4geyB0b2tlbjogYXV0aEpzb24udG9rZW4sIGV4cGlyZXNBdCB9O1xufVxuXG4vKipcbiAqIFBvbGwgdGhlIFRFRSAvcGVybWlzc2lvbiBlbmRwb2ludCB1bnRpbCB0aGUgZ2l2ZW4gUERBIGhhcyBhdXRob3JpemVkIHVzZXJzLFxuICogaW5kaWNhdGluZyBkZWxlZ2F0aW9uIGlzIGFjdGl2ZS4gUmV0dXJucyBmYWxzZSBvbiB0aW1lb3V0IChkb2VzIG5vdCB0aHJvdykuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB3YWl0VW50aWxQZXJtaXNzaW9uQWN0aXZlKFxuICB0ZWVVcmxXaXRoVG9rZW46IHN0cmluZyxcbiAgcGRhOiBBZGRyZXNzLFxuICB0aW1lb3V0TXMgPSAzMDAwMCxcbik6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAvLyBQYXJzZSBVUkw6IFwiaHR0cHM6Ly9ob3N0L3BhdGg/dG9rZW49eHh4XCIgLT4gYmFzZVVybD1cImh0dHBzOi8vaG9zdC9wYXRoXCIsIHRva2VuUGFyYW09XCJ0b2tlbj14eHhcIlxuICBjb25zdCBbYmFzZVVybCwgdG9rZW5QYXJhbV0gPSB0ZWVVcmxXaXRoVG9rZW4ucmVwbGFjZShcIi8/XCIsIFwiP1wiKS5zcGxpdChcIj9cIik7XG4gIGxldCBwZXJtaXNzaW9uVXJsOiBzdHJpbmc7XG4gIGlmICh0b2tlblBhcmFtKSB7XG4gICAgcGVybWlzc2lvblVybCA9IGAke2Jhc2VVcmx9L3Blcm1pc3Npb24/JHt0b2tlblBhcmFtfSZwdWJrZXk9JHtwZGF9YDtcbiAgfSBlbHNlIHtcbiAgICBwZXJtaXNzaW9uVXJsID0gYCR7YmFzZVVybH0vcGVybWlzc2lvbj9wdWJrZXk9JHtwZGF9YDtcbiAgfVxuXG4gIGNvbnN0IHN0YXJ0ID0gRGF0ZS5ub3coKTtcbiAgd2hpbGUgKERhdGUubm93KCkgLSBzdGFydCA8IHRpbWVvdXRNcykge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXMgPSBhd2FpdCBmZXRjaChwZXJtaXNzaW9uVXJsKTtcbiAgICAgIGlmIChyZXMub2spIHtcbiAgICAgICAgY29uc3QgeyBhdXRob3JpemVkVXNlcnMgfSA9IChhd2FpdCByZXMuanNvbigpKSBhcyB7IGF1dGhvcml6ZWRVc2Vycz86IHVua25vd25bXSB9O1xuICAgICAgICBpZiAoYXV0aG9yaXplZFVzZXJzICYmIGF1dGhvcml6ZWRVc2Vycy5sZW5ndGggPiAwKSByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIHtcbiAgICAgIC8vIGlnbm9yZSB0cmFuc2llbnQgZXJyb3JzLCBrZWVwIHBvbGxpbmdcbiAgICB9XG4gICAgYXdhaXQgbmV3IFByb21pc2UoKHIpID0+IHNldFRpbWVvdXQociwgNDAwKSk7XG4gIH1cbiAgcmV0dXJuIGZhbHNlO1xufVxuIl19
@@ -0,0 +1,11 @@
1
+ import { type Instruction, type SolanaRpcApi, type Rpc, type TransactionSigner } from "@solana/kit";
2
+ type SolanaRpc = Rpc<SolanaRpcApi>;
3
+ /**
4
+ * Build, sign with a Kit keypair signer, and send a single instruction.
5
+ */
6
+ export declare function sendInstruction(rpc: SolanaRpc, instruction: Instruction, signer: TransactionSigner): Promise<string>;
7
+ /**
8
+ * Build, sign, and send multiple instructions in a single transaction.
9
+ */
10
+ export declare function sendInstructions(rpc: SolanaRpc, instructions: Instruction[], signer: TransactionSigner): Promise<string>;
11
+ export {};
@@ -0,0 +1,50 @@
1
+ import { createTransactionMessage, setTransactionMessageFeePayerSigner, setTransactionMessageLifetimeUsingBlockhash, appendTransactionMessageInstruction, appendTransactionMessageInstructions, signTransactionMessageWithSigners, getBase64EncodedWireTransaction, pipe, } from "@solana/kit";
2
+ /**
3
+ * Build, sign with a Kit keypair signer, and send a single instruction.
4
+ */
5
+ export async function sendInstruction(rpc, instruction, signer) {
6
+ const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
7
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
8
+ const tx = pipe(createTransactionMessage({ version: 0 }), (m) => setTransactionMessageFeePayerSigner(signer, m), (m) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, m), (m) => appendTransactionMessageInstruction(instruction, m));
9
+ const signedTx = await signTransactionMessageWithSigners(tx);
10
+ const encoded = getBase64EncodedWireTransaction(signedTx);
11
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
12
+ const sig = await rpc.sendTransaction(encoded, {
13
+ encoding: "base64",
14
+ skipPreflight: true,
15
+ }).send();
16
+ // Poll for status to detect runtime errors
17
+ for (let i = 0; i < 8; i++) {
18
+ await new Promise(r => setTimeout(r, 1000));
19
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
20
+ const statuses = await rpc.getSignatureStatuses([sig], { searchTransactionHistory: false }).send().catch(() => null);
21
+ const status = statuses?.value?.[0];
22
+ if (status) {
23
+ if (status.err) {
24
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
25
+ console.error(`[TX] ${sig.slice(0, 16)}... FAILED:`, JSON.stringify(status.err, (_, v) => typeof v === 'bigint' ? v.toString() : v));
26
+ }
27
+ else if (status.confirmationStatus) {
28
+ console.log(`[TX] ${sig.slice(0, 16)}... ${status.confirmationStatus}`);
29
+ }
30
+ break;
31
+ }
32
+ }
33
+ return sig;
34
+ }
35
+ /**
36
+ * Build, sign, and send multiple instructions in a single transaction.
37
+ */
38
+ export async function sendInstructions(rpc, instructions, signer) {
39
+ const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
40
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
41
+ const tx = pipe(createTransactionMessage({ version: 0 }), (m) => setTransactionMessageFeePayerSigner(signer, m), (m) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, m), (m) => appendTransactionMessageInstructions(instructions, m));
42
+ const signedTx = await signTransactionMessageWithSigners(tx);
43
+ const encoded = getBase64EncodedWireTransaction(signedTx);
44
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
45
+ return rpc.sendTransaction(encoded, {
46
+ encoding: "base64",
47
+ skipPreflight: true,
48
+ }).send();
49
+ }
50
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNhY3Rpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdHJhbnNhY3Rpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLHdCQUF3QixFQUN4QixtQ0FBbUMsRUFDbkMsMkNBQTJDLEVBQzNDLG1DQUFtQyxFQUNuQyxvQ0FBb0MsRUFDcEMsaUNBQWlDLEVBQ2pDLCtCQUErQixFQUMvQixJQUFJLEdBS0wsTUFBTSxhQUFhLENBQUM7QUFJckI7O0dBRUc7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLGVBQWUsQ0FDbkMsR0FBYyxFQUNkLFdBQXdCLEVBQ3hCLE1BQXlCO0lBRXpCLE1BQU0sRUFBRSxLQUFLLEVBQUUsZUFBZSxFQUFFLEdBQUcsTUFBTSxHQUFHLENBQUMsa0JBQWtCLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUV6RSw4REFBOEQ7SUFDOUQsTUFBTSxFQUFFLEdBQVEsSUFBSSxDQUNsQix3QkFBd0IsQ0FBQyxFQUFFLE9BQU8sRUFBRSxDQUFVLEVBQUUsQ0FBQyxFQUNqRCxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsbUNBQW1DLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxFQUNyRCxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsMkNBQTJDLENBQUMsZUFBZSxFQUFFLENBQUMsQ0FBQyxFQUN0RSxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsbUNBQW1DLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQyxDQUMzRCxDQUFDO0lBRUYsTUFBTSxRQUFRLEdBQUcsTUFBTSxpQ0FBaUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUM3RCxNQUFNLE9BQU8sR0FBRywrQkFBK0IsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUUxRCw4REFBOEQ7SUFDOUQsTUFBTSxHQUFHLEdBQUcsTUFBTyxHQUFHLENBQUMsZUFBZSxDQUFDLE9BQWMsRUFBRTtRQUNyRCxRQUFRLEVBQUUsUUFBUTtRQUNsQixhQUFhLEVBQUUsSUFBSTtLQUNwQixDQUFDLENBQUMsSUFBSSxFQUFzQixDQUFDO0lBRTlCLDJDQUEyQztJQUMzQyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7UUFDM0IsTUFBTSxJQUFJLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUM1Qyw4REFBOEQ7UUFDOUQsTUFBTSxRQUFRLEdBQUcsTUFBTyxHQUFXLENBQUMsb0JBQW9CLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLHdCQUF3QixFQUFFLEtBQUssRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzlILE1BQU0sTUFBTSxHQUFHLFFBQVEsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNwQyxJQUFJLE1BQU0sRUFBRSxDQUFDO1lBQ1gsSUFBSSxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUM7Z0JBQ2YsOERBQThEO2dCQUM5RCxPQUFPLENBQUMsS0FBSyxDQUFDLFFBQVEsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLGFBQWEsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUN2SSxDQUFDO2lCQUFNLElBQUksTUFBTSxDQUFDLGtCQUFrQixFQUFFLENBQUM7Z0JBQ3JDLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsT0FBTyxNQUFNLENBQUMsa0JBQWtCLEVBQUUsQ0FBQyxDQUFDO1lBQzFFLENBQUM7WUFDRCxNQUFNO1FBQ1IsQ0FBQztJQUNILENBQUM7SUFDRCxPQUFPLEdBQUcsQ0FBQztBQUNiLENBQUM7QUFFRDs7R0FFRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsZ0JBQWdCLENBQ3BDLEdBQWMsRUFDZCxZQUEyQixFQUMzQixNQUF5QjtJQUV6QixNQUFNLEVBQUUsS0FBSyxFQUFFLGVBQWUsRUFBRSxHQUFHLE1BQU0sR0FBRyxDQUFDLGtCQUFrQixFQUFFLENBQUMsSUFBSSxFQUFFLENBQUM7SUFFekUsOERBQThEO0lBQzlELE1BQU0sRUFBRSxHQUFRLElBQUksQ0FDbEIsd0JBQXdCLENBQUMsRUFBRSxPQUFPLEVBQUUsQ0FBVSxFQUFFLENBQUMsRUFDakQsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLG1DQUFtQyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsRUFDckQsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLDJDQUEyQyxDQUFDLGVBQWUsRUFBRSxDQUFDLENBQUMsRUFDdEUsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLG9DQUFvQyxDQUFDLFlBQVksRUFBRSxDQUFDLENBQUMsQ0FDN0QsQ0FBQztJQUVGLE1BQU0sUUFBUSxHQUFHLE1BQU0saUNBQWlDLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDN0QsTUFBTSxPQUFPLEdBQUcsK0JBQStCLENBQUMsUUFBUSxDQUFDLENBQUM7SUFFMUQsOERBQThEO0lBQzlELE9BQU8sR0FBRyxDQUFDLGVBQWUsQ0FBQyxPQUFjLEVBQUU7UUFDekMsUUFBUSxFQUFFLFFBQVE7UUFDbEIsYUFBYSxFQUFFLElBQUk7S0FDcEIsQ0FBQyxDQUFDLElBQUksRUFBcUIsQ0FBQztBQUMvQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgY3JlYXRlVHJhbnNhY3Rpb25NZXNzYWdlLFxuICBzZXRUcmFuc2FjdGlvbk1lc3NhZ2VGZWVQYXllclNpZ25lcixcbiAgc2V0VHJhbnNhY3Rpb25NZXNzYWdlTGlmZXRpbWVVc2luZ0Jsb2NraGFzaCxcbiAgYXBwZW5kVHJhbnNhY3Rpb25NZXNzYWdlSW5zdHJ1Y3Rpb24sXG4gIGFwcGVuZFRyYW5zYWN0aW9uTWVzc2FnZUluc3RydWN0aW9ucyxcbiAgc2lnblRyYW5zYWN0aW9uTWVzc2FnZVdpdGhTaWduZXJzLFxuICBnZXRCYXNlNjRFbmNvZGVkV2lyZVRyYW5zYWN0aW9uLFxuICBwaXBlLFxuICB0eXBlIEluc3RydWN0aW9uLFxuICB0eXBlIFNvbGFuYVJwY0FwaSxcbiAgdHlwZSBScGMsXG4gIHR5cGUgVHJhbnNhY3Rpb25TaWduZXIsXG59IGZyb20gXCJAc29sYW5hL2tpdFwiO1xuXG50eXBlIFNvbGFuYVJwYyA9IFJwYzxTb2xhbmFScGNBcGk+O1xuXG4vKipcbiAqIEJ1aWxkLCBzaWduIHdpdGggYSBLaXQga2V5cGFpciBzaWduZXIsIGFuZCBzZW5kIGEgc2luZ2xlIGluc3RydWN0aW9uLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2VuZEluc3RydWN0aW9uKFxuICBycGM6IFNvbGFuYVJwYyxcbiAgaW5zdHJ1Y3Rpb246IEluc3RydWN0aW9uLFxuICBzaWduZXI6IFRyYW5zYWN0aW9uU2lnbmVyLFxuKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgY29uc3QgeyB2YWx1ZTogbGF0ZXN0QmxvY2toYXNoIH0gPSBhd2FpdCBycGMuZ2V0TGF0ZXN0QmxvY2toYXNoKCkuc2VuZCgpO1xuXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gIGNvbnN0IHR4OiBhbnkgPSBwaXBlKFxuICAgIGNyZWF0ZVRyYW5zYWN0aW9uTWVzc2FnZSh7IHZlcnNpb246IDAgYXMgY29uc3QgfSksXG4gICAgKG0pID0+IHNldFRyYW5zYWN0aW9uTWVzc2FnZUZlZVBheWVyU2lnbmVyKHNpZ25lciwgbSksXG4gICAgKG0pID0+IHNldFRyYW5zYWN0aW9uTWVzc2FnZUxpZmV0aW1lVXNpbmdCbG9ja2hhc2gobGF0ZXN0QmxvY2toYXNoLCBtKSxcbiAgICAobSkgPT4gYXBwZW5kVHJhbnNhY3Rpb25NZXNzYWdlSW5zdHJ1Y3Rpb24oaW5zdHJ1Y3Rpb24sIG0pLFxuICApO1xuXG4gIGNvbnN0IHNpZ25lZFR4ID0gYXdhaXQgc2lnblRyYW5zYWN0aW9uTWVzc2FnZVdpdGhTaWduZXJzKHR4KTtcbiAgY29uc3QgZW5jb2RlZCA9IGdldEJhc2U2NEVuY29kZWRXaXJlVHJhbnNhY3Rpb24oc2lnbmVkVHgpO1xuXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gIGNvbnN0IHNpZyA9IGF3YWl0IChycGMuc2VuZFRyYW5zYWN0aW9uKGVuY29kZWQgYXMgYW55LCB7XG4gICAgZW5jb2Rpbmc6IFwiYmFzZTY0XCIsXG4gICAgc2tpcFByZWZsaWdodDogdHJ1ZSxcbiAgfSkuc2VuZCgpIGFzIFByb21pc2U8c3RyaW5nPik7XG5cbiAgLy8gUG9sbCBmb3Igc3RhdHVzIHRvIGRldGVjdCBydW50aW1lIGVycm9yc1xuICBmb3IgKGxldCBpID0gMDsgaSA8IDg7IGkrKykge1xuICAgIGF3YWl0IG5ldyBQcm9taXNlKHIgPT4gc2V0VGltZW91dChyLCAxMDAwKSk7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICBjb25zdCBzdGF0dXNlcyA9IGF3YWl0IChycGMgYXMgYW55KS5nZXRTaWduYXR1cmVTdGF0dXNlcyhbc2lnXSwgeyBzZWFyY2hUcmFuc2FjdGlvbkhpc3Rvcnk6IGZhbHNlIH0pLnNlbmQoKS5jYXRjaCgoKSA9PiBudWxsKTtcbiAgICBjb25zdCBzdGF0dXMgPSBzdGF0dXNlcz8udmFsdWU/LlswXTtcbiAgICBpZiAoc3RhdHVzKSB7XG4gICAgICBpZiAoc3RhdHVzLmVycikge1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgICAgICBjb25zb2xlLmVycm9yKGBbVFhdICR7c2lnLnNsaWNlKDAsIDE2KX0uLi4gRkFJTEVEOmAsIEpTT04uc3RyaW5naWZ5KHN0YXR1cy5lcnIsIChfLCB2KSA9PiB0eXBlb2YgdiA9PT0gJ2JpZ2ludCcgPyB2LnRvU3RyaW5nKCkgOiB2KSk7XG4gICAgICB9IGVsc2UgaWYgKHN0YXR1cy5jb25maXJtYXRpb25TdGF0dXMpIHtcbiAgICAgICAgY29uc29sZS5sb2coYFtUWF0gJHtzaWcuc2xpY2UoMCwgMTYpfS4uLiAke3N0YXR1cy5jb25maXJtYXRpb25TdGF0dXN9YCk7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHNpZztcbn1cblxuLyoqXG4gKiBCdWlsZCwgc2lnbiwgYW5kIHNlbmQgbXVsdGlwbGUgaW5zdHJ1Y3Rpb25zIGluIGEgc2luZ2xlIHRyYW5zYWN0aW9uLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2VuZEluc3RydWN0aW9ucyhcbiAgcnBjOiBTb2xhbmFScGMsXG4gIGluc3RydWN0aW9uczogSW5zdHJ1Y3Rpb25bXSxcbiAgc2lnbmVyOiBUcmFuc2FjdGlvblNpZ25lcixcbik6IFByb21pc2U8c3RyaW5nPiB7XG4gIGNvbnN0IHsgdmFsdWU6IGxhdGVzdEJsb2NraGFzaCB9ID0gYXdhaXQgcnBjLmdldExhdGVzdEJsb2NraGFzaCgpLnNlbmQoKTtcblxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICBjb25zdCB0eDogYW55ID0gcGlwZShcbiAgICBjcmVhdGVUcmFuc2FjdGlvbk1lc3NhZ2UoeyB2ZXJzaW9uOiAwIGFzIGNvbnN0IH0pLFxuICAgIChtKSA9PiBzZXRUcmFuc2FjdGlvbk1lc3NhZ2VGZWVQYXllclNpZ25lcihzaWduZXIsIG0pLFxuICAgIChtKSA9PiBzZXRUcmFuc2FjdGlvbk1lc3NhZ2VMaWZldGltZVVzaW5nQmxvY2toYXNoKGxhdGVzdEJsb2NraGFzaCwgbSksXG4gICAgKG0pID0+IGFwcGVuZFRyYW5zYWN0aW9uTWVzc2FnZUluc3RydWN0aW9ucyhpbnN0cnVjdGlvbnMsIG0pLFxuICApO1xuXG4gIGNvbnN0IHNpZ25lZFR4ID0gYXdhaXQgc2lnblRyYW5zYWN0aW9uTWVzc2FnZVdpdGhTaWduZXJzKHR4KTtcbiAgY29uc3QgZW5jb2RlZCA9IGdldEJhc2U2NEVuY29kZWRXaXJlVHJhbnNhY3Rpb24oc2lnbmVkVHgpO1xuXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gIHJldHVybiBycGMuc2VuZFRyYW5zYWN0aW9uKGVuY29kZWQgYXMgYW55LCB7XG4gICAgZW5jb2Rpbmc6IFwiYmFzZTY0XCIsXG4gICAgc2tpcFByZWZsaWdodDogdHJ1ZSxcbiAgfSkuc2VuZCgpIGFzIFByb21pc2U8c3RyaW5nPjtcbn1cbiJdfQ==
package/dist/utils.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import * as web3 from "@solana/web3.js";
1
+ import { type Address } from "@solana/kit";
2
2
  export declare const QUEUE_SEED = "queue";
3
3
  export declare const TENANT_SEED = "tenant";
4
4
  export declare const TICKET_SEED = "ticket";
5
- export declare function deriveQueuePda(programId: web3.PublicKey, authority: web3.PublicKey): web3.PublicKey;
6
- export declare function deriveTenantPda(programId: web3.PublicKey, authority: web3.PublicKey): web3.PublicKey;
7
- export declare function deriveTicketPda(programId: web3.PublicKey, player: web3.PublicKey, tenant: web3.PublicKey): web3.PublicKey;
5
+ export declare function deriveQueuePda(programId: Address, authority: Address): Promise<Address>;
6
+ export declare function deriveTenantPda(programId: Address, authority: Address): Promise<Address>;
7
+ export declare function deriveTicketPda(programId: Address, player: Address, tenant: Address): Promise<Address>;
package/dist/utils.js CHANGED
@@ -1,17 +1,32 @@
1
- import * as web3 from "@solana/web3.js";
1
+ import { getProgramDerivedAddress, getAddressEncoder, getUtf8Encoder, } from "@solana/kit";
2
+ const addressEncoder = getAddressEncoder();
3
+ const utf8Encoder = getUtf8Encoder();
2
4
  export const QUEUE_SEED = "queue";
3
5
  export const TENANT_SEED = "tenant";
4
6
  export const TICKET_SEED = "ticket";
5
- export function deriveQueuePda(programId, authority) {
6
- const [pda] = web3.PublicKey.findProgramAddressSync([Buffer.from(QUEUE_SEED), authority.toBuffer()], programId);
7
+ export async function deriveQueuePda(programId, authority) {
8
+ const [pda] = await getProgramDerivedAddress({
9
+ programAddress: programId,
10
+ seeds: [utf8Encoder.encode(QUEUE_SEED), addressEncoder.encode(authority)],
11
+ });
7
12
  return pda;
8
13
  }
9
- export function deriveTenantPda(programId, authority) {
10
- const [pda] = web3.PublicKey.findProgramAddressSync([Buffer.from(TENANT_SEED), authority.toBuffer()], programId);
14
+ export async function deriveTenantPda(programId, authority) {
15
+ const [pda] = await getProgramDerivedAddress({
16
+ programAddress: programId,
17
+ seeds: [utf8Encoder.encode(TENANT_SEED), addressEncoder.encode(authority)],
18
+ });
11
19
  return pda;
12
20
  }
13
- export function deriveTicketPda(programId, player, tenant) {
14
- const [pda] = web3.PublicKey.findProgramAddressSync([Buffer.from(TICKET_SEED), player.toBuffer(), tenant.toBuffer()], programId);
21
+ export async function deriveTicketPda(programId, player, tenant) {
22
+ const [pda] = await getProgramDerivedAddress({
23
+ programAddress: programId,
24
+ seeds: [
25
+ utf8Encoder.encode(TICKET_SEED),
26
+ addressEncoder.encode(player),
27
+ addressEncoder.encode(tenant),
28
+ ],
29
+ });
15
30
  return pda;
16
31
  }
17
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLElBQUksTUFBTSxpQkFBaUIsQ0FBQztBQUd4QyxNQUFNLENBQUMsTUFBTSxVQUFVLEdBQUcsT0FBTyxDQUFDO0FBQ2xDLE1BQU0sQ0FBQyxNQUFNLFdBQVcsR0FBRyxRQUFRLENBQUM7QUFDcEMsTUFBTSxDQUFDLE1BQU0sV0FBVyxHQUFHLFFBQVEsQ0FBQztBQUVwQyxNQUFNLFVBQVUsY0FBYyxDQUFDLFNBQXlCLEVBQUUsU0FBeUI7SUFDL0UsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsc0JBQXNCLENBQy9DLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsRUFBRSxTQUFTLENBQUMsUUFBUSxFQUFFLENBQUMsRUFDL0MsU0FBUyxDQUNaLENBQUM7SUFDRixPQUFPLEdBQUcsQ0FBQztBQUNmLENBQUM7QUFFRCxNQUFNLFVBQVUsZUFBZSxDQUFDLFNBQXlCLEVBQUUsU0FBeUI7SUFDaEYsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsc0JBQXNCLENBQy9DLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsRUFBRSxTQUFTLENBQUMsUUFBUSxFQUFFLENBQUMsRUFDaEQsU0FBUyxDQUNaLENBQUM7SUFDRixPQUFPLEdBQUcsQ0FBQztBQUNmLENBQUM7QUFFRCxNQUFNLFVBQVUsZUFBZSxDQUFDLFNBQXlCLEVBQUUsTUFBc0IsRUFBRSxNQUFzQjtJQUNyRyxNQUFNLENBQUMsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxzQkFBc0IsQ0FDL0MsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxRQUFRLEVBQUUsRUFBRSxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUMsRUFDaEUsU0FBUyxDQUNaLENBQUM7SUFDRixPQUFPLEdBQUcsQ0FBQztBQUNmLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyB3ZWIzIGZyb20gXCJAc29sYW5hL3dlYjMuanNcIjtcbmltcG9ydCAqIGFzIGFuY2hvciBmcm9tIFwiQGNvcmFsLXh5ei9hbmNob3JcIjtcblxuZXhwb3J0IGNvbnN0IFFVRVVFX1NFRUQgPSBcInF1ZXVlXCI7XG5leHBvcnQgY29uc3QgVEVOQU5UX1NFRUQgPSBcInRlbmFudFwiO1xuZXhwb3J0IGNvbnN0IFRJQ0tFVF9TRUVEID0gXCJ0aWNrZXRcIjtcblxuZXhwb3J0IGZ1bmN0aW9uIGRlcml2ZVF1ZXVlUGRhKHByb2dyYW1JZDogd2ViMy5QdWJsaWNLZXksIGF1dGhvcml0eTogd2ViMy5QdWJsaWNLZXkpOiB3ZWIzLlB1YmxpY0tleSB7XG4gICAgY29uc3QgW3BkYV0gPSB3ZWIzLlB1YmxpY0tleS5maW5kUHJvZ3JhbUFkZHJlc3NTeW5jKFxuICAgICAgICBbQnVmZmVyLmZyb20oUVVFVUVfU0VFRCksIGF1dGhvcml0eS50b0J1ZmZlcigpXSxcbiAgICAgICAgcHJvZ3JhbUlkXG4gICAgKTtcbiAgICByZXR1cm4gcGRhO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVyaXZlVGVuYW50UGRhKHByb2dyYW1JZDogd2ViMy5QdWJsaWNLZXksIGF1dGhvcml0eTogd2ViMy5QdWJsaWNLZXkpOiB3ZWIzLlB1YmxpY0tleSB7XG4gICAgY29uc3QgW3BkYV0gPSB3ZWIzLlB1YmxpY0tleS5maW5kUHJvZ3JhbUFkZHJlc3NTeW5jKFxuICAgICAgICBbQnVmZmVyLmZyb20oVEVOQU5UX1NFRUQpLCBhdXRob3JpdHkudG9CdWZmZXIoKV0sXG4gICAgICAgIHByb2dyYW1JZFxuICAgICk7XG4gICAgcmV0dXJuIHBkYTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGRlcml2ZVRpY2tldFBkYShwcm9ncmFtSWQ6IHdlYjMuUHVibGljS2V5LCBwbGF5ZXI6IHdlYjMuUHVibGljS2V5LCB0ZW5hbnQ6IHdlYjMuUHVibGljS2V5KTogd2ViMy5QdWJsaWNLZXkge1xuICAgIGNvbnN0IFtwZGFdID0gd2ViMy5QdWJsaWNLZXkuZmluZFByb2dyYW1BZGRyZXNzU3luYyhcbiAgICAgICAgW0J1ZmZlci5mcm9tKFRJQ0tFVF9TRUVEKSwgcGxheWVyLnRvQnVmZmVyKCksIHRlbmFudC50b0J1ZmZlcigpXSxcbiAgICAgICAgcHJvZ3JhbUlkXG4gICAgKTtcbiAgICByZXR1cm4gcGRhO1xufVxuIl19
32
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLHdCQUF3QixFQUN4QixpQkFBaUIsRUFDakIsY0FBYyxHQUVmLE1BQU0sYUFBYSxDQUFDO0FBRXJCLE1BQU0sY0FBYyxHQUFHLGlCQUFpQixFQUFFLENBQUM7QUFDM0MsTUFBTSxXQUFXLEdBQUcsY0FBYyxFQUFFLENBQUM7QUFFckMsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQztBQUNsQyxNQUFNLENBQUMsTUFBTSxXQUFXLEdBQUcsUUFBUSxDQUFDO0FBQ3BDLE1BQU0sQ0FBQyxNQUFNLFdBQVcsR0FBRyxRQUFRLENBQUM7QUFFcEMsTUFBTSxDQUFDLEtBQUssVUFBVSxjQUFjLENBQUMsU0FBa0IsRUFBRSxTQUFrQjtJQUN6RSxNQUFNLENBQUMsR0FBRyxDQUFDLEdBQUcsTUFBTSx3QkFBd0IsQ0FBQztRQUMzQyxjQUFjLEVBQUUsU0FBUztRQUN6QixLQUFLLEVBQUUsQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxFQUFFLGNBQWMsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUM7S0FDMUUsQ0FBQyxDQUFDO0lBQ0gsT0FBTyxHQUFHLENBQUM7QUFDYixDQUFDO0FBRUQsTUFBTSxDQUFDLEtBQUssVUFBVSxlQUFlLENBQUMsU0FBa0IsRUFBRSxTQUFrQjtJQUMxRSxNQUFNLENBQUMsR0FBRyxDQUFDLEdBQUcsTUFBTSx3QkFBd0IsQ0FBQztRQUMzQyxjQUFjLEVBQUUsU0FBUztRQUN6QixLQUFLLEVBQUUsQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxFQUFFLGNBQWMsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUM7S0FDM0UsQ0FBQyxDQUFDO0lBQ0gsT0FBTyxHQUFHLENBQUM7QUFDYixDQUFDO0FBRUQsTUFBTSxDQUFDLEtBQUssVUFBVSxlQUFlLENBQ25DLFNBQWtCLEVBQ2xCLE1BQWUsRUFDZixNQUFlO0lBRWYsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLE1BQU0sd0JBQXdCLENBQUM7UUFDM0MsY0FBYyxFQUFFLFNBQVM7UUFDekIsS0FBSyxFQUFFO1lBQ0wsV0FBVyxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUM7WUFDL0IsY0FBYyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUM7WUFDN0IsY0FBYyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUM7U0FDOUI7S0FDRixDQUFDLENBQUM7SUFDSCxPQUFPLEdBQUcsQ0FBQztBQUNiLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBnZXRQcm9ncmFtRGVyaXZlZEFkZHJlc3MsXG4gIGdldEFkZHJlc3NFbmNvZGVyLFxuICBnZXRVdGY4RW5jb2RlcixcbiAgdHlwZSBBZGRyZXNzLFxufSBmcm9tIFwiQHNvbGFuYS9raXRcIjtcblxuY29uc3QgYWRkcmVzc0VuY29kZXIgPSBnZXRBZGRyZXNzRW5jb2RlcigpO1xuY29uc3QgdXRmOEVuY29kZXIgPSBnZXRVdGY4RW5jb2RlcigpO1xuXG5leHBvcnQgY29uc3QgUVVFVUVfU0VFRCA9IFwicXVldWVcIjtcbmV4cG9ydCBjb25zdCBURU5BTlRfU0VFRCA9IFwidGVuYW50XCI7XG5leHBvcnQgY29uc3QgVElDS0VUX1NFRUQgPSBcInRpY2tldFwiO1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZGVyaXZlUXVldWVQZGEocHJvZ3JhbUlkOiBBZGRyZXNzLCBhdXRob3JpdHk6IEFkZHJlc3MpOiBQcm9taXNlPEFkZHJlc3M+IHtcbiAgY29uc3QgW3BkYV0gPSBhd2FpdCBnZXRQcm9ncmFtRGVyaXZlZEFkZHJlc3Moe1xuICAgIHByb2dyYW1BZGRyZXNzOiBwcm9ncmFtSWQsXG4gICAgc2VlZHM6IFt1dGY4RW5jb2Rlci5lbmNvZGUoUVVFVUVfU0VFRCksIGFkZHJlc3NFbmNvZGVyLmVuY29kZShhdXRob3JpdHkpXSxcbiAgfSk7XG4gIHJldHVybiBwZGE7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkZXJpdmVUZW5hbnRQZGEocHJvZ3JhbUlkOiBBZGRyZXNzLCBhdXRob3JpdHk6IEFkZHJlc3MpOiBQcm9taXNlPEFkZHJlc3M+IHtcbiAgY29uc3QgW3BkYV0gPSBhd2FpdCBnZXRQcm9ncmFtRGVyaXZlZEFkZHJlc3Moe1xuICAgIHByb2dyYW1BZGRyZXNzOiBwcm9ncmFtSWQsXG4gICAgc2VlZHM6IFt1dGY4RW5jb2Rlci5lbmNvZGUoVEVOQU5UX1NFRUQpLCBhZGRyZXNzRW5jb2Rlci5lbmNvZGUoYXV0aG9yaXR5KV0sXG4gIH0pO1xuICByZXR1cm4gcGRhO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZGVyaXZlVGlja2V0UGRhKFxuICBwcm9ncmFtSWQ6IEFkZHJlc3MsXG4gIHBsYXllcjogQWRkcmVzcyxcbiAgdGVuYW50OiBBZGRyZXNzXG4pOiBQcm9taXNlPEFkZHJlc3M+IHtcbiAgY29uc3QgW3BkYV0gPSBhd2FpdCBnZXRQcm9ncmFtRGVyaXZlZEFkZHJlc3Moe1xuICAgIHByb2dyYW1BZGRyZXNzOiBwcm9ncmFtSWQsXG4gICAgc2VlZHM6IFtcbiAgICAgIHV0ZjhFbmNvZGVyLmVuY29kZShUSUNLRVRfU0VFRCksXG4gICAgICBhZGRyZXNzRW5jb2Rlci5lbmNvZGUocGxheWVyKSxcbiAgICAgIGFkZHJlc3NFbmNvZGVyLmVuY29kZSh0ZW5hbnQpLFxuICAgIF0sXG4gIH0pO1xuICByZXR1cm4gcGRhO1xufVxuIl19
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@1upmonster/duel",
3
- "version": "0.1.8",
3
+ "version": "0.2.2",
4
4
  "type": "module",
5
5
  "description": "SDK for Private Matchmaking on Solana",
6
6
  "license": "MIT",
@@ -15,13 +15,10 @@
15
15
  "prepublishOnly": "npm run build"
16
16
  },
17
17
  "dependencies": {
18
- "@coral-xyz/anchor": "^0.32.1",
19
- "@magicblock-labs/ephemeral-rollups-sdk": "0.8.0",
20
- "@solana/web3.js": "^1.95.3",
21
- "bn.js": "^5.2.1"
18
+ "@solana/kit": "^6.1.0",
19
+ "@solana/program-client-core": "^6.1.0"
22
20
  },
23
21
  "devDependencies": {
24
- "@types/bn.js": "^5.1.0",
25
22
  "@types/node": "^16.0.0",
26
23
  "typescript": "~5.7.0"
27
24
  }
package/src/admin.ts CHANGED
@@ -1,211 +1,201 @@
1
- import * as anchor from "@coral-xyz/anchor";
2
- import { BN } from "bn.js";
3
- import * as web3 from "@solana/web3.js";
4
- import type { Duel } from "./types.js";
5
- import IDL from "./duel.json" with { type: "json" };
1
+ import {
2
+ createSolanaRpc,
3
+ type Address,
4
+ type TransactionSigner,
5
+ type Rpc,
6
+ type SolanaRpcApi,
7
+ } from "@solana/kit";
8
+ import {
9
+ getInitializeTenantInstructionAsync,
10
+ getInitializeQueueInstructionAsync,
11
+ getDelegateQueueInstructionAsync,
12
+ getFlushMatchesInstruction,
13
+ getCommitTicketsInstruction,
14
+ fetchQueue,
15
+ accountType,
16
+ } from "./generated/duel/index.js";
17
+ import { sendInstruction } from "./transaction.js";
6
18
  import * as utils from "./utils.js";
7
19
 
8
- const TICKET_SEED = "ticket";
9
-
10
- export type EloDataType = 'u8' | 'u16' | 'u32' | 'u64';
20
+ export type EloDataType = "u8" | "u16" | "u32" | "u64";
11
21
 
12
22
  export interface InitializeTenantOptions {
13
- authority?: web3.PublicKey;
14
- eloWindow?: number;
23
+ authority?: Address;
24
+ eloWindow?: bigint;
15
25
  eloOffset?: number;
16
26
  eloDataType?: EloDataType;
17
- callbackProgramId?: web3.PublicKey | null;
27
+ callbackProgramId?: Address | null;
18
28
  callbackDiscriminator?: number[] | null;
19
29
  }
20
30
 
21
31
  function getEloSize(dataType: EloDataType): number {
22
32
  switch (dataType) {
23
- case 'u8': return 1;
24
- case 'u16': return 2;
25
- case 'u32': return 4;
26
- case 'u64': return 8;
33
+ case "u8": return 1;
34
+ case "u16": return 2;
35
+ case "u32": return 4;
36
+ case "u64": return 8;
27
37
  }
28
38
  }
29
39
 
30
- export class MatchmakingAdmin {
31
- public program: anchor.Program<Duel>;
32
- public provider: anchor.AnchorProvider;
33
-
34
- constructor(provider: anchor.AnchorProvider, programId: web3.PublicKey | string) {
35
- const address = typeof programId === "string" ? programId : programId.toBase58();
36
- const idl = { ...IDL, address };
37
- this.program = new anchor.Program(idl as any, provider);
38
- this.provider = provider;
39
- }
40
+ const DUEL_PROGRAM_ID = "EdZzUwKd1X2ZWjxLPpz1cpEzMF7RUZC43Pq64v1VcK5X" as Address;
40
41
 
41
- // Derive PDAs Helpers
42
- getQueuePda(authority: web3.PublicKey): web3.PublicKey {
43
- return utils.deriveQueuePda(this.program.programId, authority);
42
+ export class MatchmakingAdmin {
43
+ public rpc: Rpc<SolanaRpcApi>;
44
+ public signer: TransactionSigner;
45
+ public programId: Address;
46
+
47
+ constructor(
48
+ rpc: Rpc<SolanaRpcApi>,
49
+ signer: TransactionSigner,
50
+ programId: Address = DUEL_PROGRAM_ID,
51
+ ) {
52
+ this.rpc = rpc;
53
+ this.signer = signer;
54
+ this.programId = programId;
44
55
  }
45
56
 
46
- getTenantPda(authority: web3.PublicKey): web3.PublicKey {
47
- return utils.deriveTenantPda(this.program.programId, authority);
57
+ async getQueuePda(authority: Address): Promise<Address> {
58
+ return utils.deriveQueuePda(this.programId, authority);
48
59
  }
49
60
 
50
- getTicketPda(player: web3.PublicKey, tenant: web3.PublicKey): web3.PublicKey {
51
- return utils.deriveTicketPda(this.program.programId, player, tenant);
61
+ async getTenantPda(authority: Address): Promise<Address> {
62
+ return utils.deriveTenantPda(this.programId, authority);
52
63
  }
53
64
 
54
- /**
55
- * Fetch Queue account data
56
- */
57
- async getQueue(queuePda: web3.PublicKey): Promise<any> {
58
- return await this.program.account.queue.fetch(queuePda);
65
+ async getTicketPda(player: Address, tenant: Address): Promise<Address> {
66
+ return utils.deriveTicketPda(this.programId, player, tenant);
59
67
  }
60
68
 
61
- /**
62
- * Fetch Tenant account data
63
- */
64
- async getTenant(tenantPda: web3.PublicKey): Promise<any> {
65
- return await this.program.account.tenant.fetch(tenantPda);
69
+ async getQueue(queuePda: Address) {
70
+ return fetchQueue(this.rpc, queuePda);
66
71
  }
67
72
 
68
- /**
69
- * Initialize a Tenant (with optional callback config)
70
- */
71
73
  async initializeTenant(
72
- tenantProgramId: web3.PublicKey,
74
+ tenantProgramId: Address,
73
75
  options?: InitializeTenantOptions,
74
- confirmOptions?: web3.ConfirmOptions,
75
- signers: web3.Keypair[] = []
76
- ): Promise<web3.TransactionSignature> {
76
+ ): Promise<string> {
77
77
  const {
78
- authority = tenantProgramId,
79
- eloWindow = 100,
78
+ eloWindow = 100n,
80
79
  eloOffset = 40,
81
- eloDataType = 'u16',
80
+ eloDataType = "u16",
82
81
  callbackProgramId = null,
83
82
  callbackDiscriminator = null,
84
83
  } = options || {};
85
84
 
86
85
  const eloSize = getEloSize(eloDataType);
87
- const tenantPda = this.getTenantPda(authority);
88
-
89
- return await this.program.methods
90
- .initializeTenant(
91
- tenantProgramId,
92
- eloOffset,
93
- eloSize,
94
- new BN(eloWindow),
95
- callbackProgramId || null,
96
- callbackDiscriminator ? Array.from(Buffer.from(callbackDiscriminator)) : null
97
- )
98
- .accountsPartial({
99
- tenant: tenantPda,
100
- authority: authority,
101
- })
102
- .signers(signers)
103
- .rpc(confirmOptions);
86
+ const ix = await getInitializeTenantInstructionAsync({
87
+ authority: this.signer,
88
+ tenantProgramId,
89
+ eloOffset,
90
+ eloSize,
91
+ eloWindow,
92
+ callbackProgramId: callbackProgramId ? { __option: "Some", value: callbackProgramId } : { __option: "None" },
93
+ callbackDiscriminator: callbackDiscriminator
94
+ ? { __option: "Some", value: new Uint8Array(callbackDiscriminator) }
95
+ : { __option: "None" },
96
+ }, { programAddress: this.programId });
97
+
98
+ return sendInstruction(this.rpc, ix, this.signer);
104
99
  }
105
100
 
106
- /**
107
- * Initialize a Queue
108
- */
109
101
  async initializeQueue(
110
- authority: web3.PublicKey,
111
- tenant: web3.PublicKey,
112
- confirmOptions?: web3.ConfirmOptions,
113
- signers: web3.Keypair[] = []
114
- ): Promise<web3.TransactionSignature> {
115
- const queuePda = this.getQueuePda(authority);
116
- return await this.program.methods
117
- .initializeQueue()
118
- .accountsPartial({
119
- queue: queuePda,
120
- tenant: tenant,
121
- authority: authority,
122
- })
123
- .signers(signers)
124
- .rpc(confirmOptions);
102
+ _authority: Address,
103
+ tenant: Address,
104
+ ): Promise<string> {
105
+ const ix = await getInitializeQueueInstructionAsync({
106
+ authority: this.signer,
107
+ tenant,
108
+ }, { programAddress: this.programId });
109
+ return sendInstruction(this.rpc, ix, this.signer);
125
110
  }
126
111
 
127
- /**
128
- * Delegate Queue to TEE
129
- */
130
112
  async delegateQueue(
131
- authority: web3.PublicKey,
132
- validator: web3.PublicKey = new web3.PublicKey("FnE6VJT5QNZdedZPnCoLsARgBwoE6DeJNjBs2H1gySXA"),
133
- confirmOptions?: web3.ConfirmOptions,
134
- signers: web3.Keypair[] = []
135
- ): Promise<web3.TransactionSignature> {
136
- const queuePda = this.getQueuePda(authority);
137
- return await this.program.methods
138
- .delegateQueue({ queue: { authority } } as any)
139
- .accounts({
140
- pda: queuePda,
141
- payer: authority,
142
- validator: validator,
143
- } as unknown as any)
144
- .signers(signers)
145
- .rpc(confirmOptions);
113
+ authority: Address,
114
+ validator?: Address,
115
+ ): Promise<string> {
116
+ const queuePda = await this.getQueuePda(authority);
117
+ const ix = await getDelegateQueueInstructionAsync({
118
+ pda: queuePda,
119
+ payer: this.signer,
120
+ validator,
121
+ accountType: accountType("Queue", { authority }),
122
+ }, { programAddress: this.programId });
123
+ return sendInstruction(this.rpc, ix, this.signer);
146
124
  }
147
125
 
148
- /**
149
- * Flush pending matches - crank instruction to update opponent tickets
150
- * Can be called by any TEE-authenticated wallet (permissionless)
151
- */
152
126
  async flushMatches(
153
- queue: web3.PublicKey,
154
- tenant: web3.PublicKey,
155
- ticketPdas: web3.PublicKey[],
156
- callbackProgram?: web3.PublicKey,
157
- confirmOptions?: web3.ConfirmOptions,
158
- signers: web3.Keypair[] = []
159
- ): Promise<web3.TransactionSignature> {
160
- const remainingAccounts = ticketPdas.map(pda => ({
161
- pubkey: pda,
162
- isSigner: false,
163
- isWritable: true,
164
- }));
165
-
166
- if (callbackProgram) {
167
- remainingAccounts.push({
168
- pubkey: callbackProgram,
169
- isSigner: false,
170
- isWritable: false,
171
- });
172
- }
127
+ queue: Address,
128
+ tenant: Address,
129
+ ticketPdas: Address[],
130
+ ): Promise<string> {
131
+ const ix = getFlushMatchesInstruction({
132
+ queue,
133
+ tenant,
134
+ signer: this.signer,
135
+ }, { programAddress: this.programId });
136
+
137
+ const ixWithRemaining = {
138
+ ...ix,
139
+ accounts: [
140
+ ...ix.accounts,
141
+ ...ticketPdas.map((address) => ({ address, role: 1 as const })),
142
+ ],
143
+ };
144
+
145
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
146
+ return sendInstruction(this.rpc, ixWithRemaining as any, this.signer);
147
+ }
173
148
 
174
- return await this.program.methods
175
- .flushMatches()
176
- .accountsPartial({
177
- queue: queue,
178
- tenant: tenant,
179
- signer: this.provider.publicKey,
180
- })
181
- .remainingAccounts(remainingAccounts)
182
- .signers(signers)
183
- .rpc(confirmOptions);
149
+ async commitTickets(
150
+ tenant: Address,
151
+ ticketPdas: Address[],
152
+ ): Promise<string> {
153
+ const ix = getCommitTicketsInstruction({
154
+ tenant,
155
+ payer: this.signer,
156
+ }, { programAddress: this.programId });
157
+
158
+ const ixWithRemaining = {
159
+ ...ix,
160
+ accounts: [
161
+ ...ix.accounts,
162
+ ...ticketPdas.map((address) => ({ address, role: 1 as const })),
163
+ ],
164
+ };
165
+
166
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
167
+ return sendInstruction(this.rpc, ixWithRemaining as any, this.signer);
184
168
  }
185
169
 
186
170
  /**
187
- * Commit matched tickets back to L1 (runs in TEE)
171
+ * High-level: full match resolution flow (runs on TEE).
172
+ * Reads the queue's pending matches, flushes them (updating opponent tickets),
173
+ * waits for TEE settlement, then commits all tickets back to L1.
174
+ * Use individual methods (flushMatches, commitTickets) as escape hatches if needed.
188
175
  */
189
- async commitTickets(
190
- tenant: web3.PublicKey,
191
- ticketPdas: web3.PublicKey[],
192
- confirmOptions?: web3.ConfirmOptions,
193
- signers: web3.Keypair[] = []
194
- ): Promise<web3.TransactionSignature> {
195
- return await this.program.methods
196
- .commitTickets()
197
- .accountsPartial({
198
- tenant: tenant,
199
- payer: this.provider.publicKey,
200
- })
201
- .remainingAccounts(
202
- ticketPdas.map(pda => ({
203
- pubkey: pda,
204
- isSigner: false,
205
- isWritable: true,
206
- }))
207
- )
208
- .signers(signers)
209
- .rpc(confirmOptions);
176
+ async resolveMatches(
177
+ queue: Address,
178
+ tenant: Address,
179
+ ticketPdas: Address[],
180
+ settlementDelayMs = 3000,
181
+ ): Promise<void> {
182
+ const queueData = await this.getQueue(queue);
183
+ const pendingTicketPdas = await Promise.all(
184
+ queueData.data.pendingMatches.map((pm) =>
185
+ utils.deriveTicketPda(this.programId, pm.player, tenant),
186
+ ),
187
+ );
188
+
189
+ if (pendingTicketPdas.length > 0) {
190
+ await this.flushMatches(queue, tenant, pendingTicketPdas);
191
+ await new Promise((r) => setTimeout(r, settlementDelayMs));
192
+ }
193
+
194
+ await this.commitTickets(tenant, ticketPdas);
195
+ }
196
+
197
+ /** Create a new MatchmakingAdmin pointing at a TEE RPC endpoint. */
198
+ withRpc(teeUrl: string): MatchmakingAdmin {
199
+ return new MatchmakingAdmin(createSolanaRpc(teeUrl), this.signer, this.programId);
210
200
  }
211
201
  }