@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.
- package/README.md +110 -59
- package/dist/admin.d.ts +25 -40
- package/dist/admin.js +93 -114
- package/dist/encryption.js +1 -2
- package/dist/generated/duel/accounts/index.d.ts +10 -0
- package/dist/generated/duel/accounts/index.js +11 -0
- package/dist/generated/duel/accounts/matchTicket.d.ts +38 -0
- package/dist/generated/duel/accounts/matchTicket.js +45 -0
- package/dist/generated/duel/accounts/queue.d.ts +42 -0
- package/dist/generated/duel/accounts/queue.js +45 -0
- package/dist/generated/duel/accounts/tenant.d.ts +41 -0
- package/dist/generated/duel/accounts/tenant.js +44 -0
- package/dist/generated/duel/errors/duel.d.ts +31 -0
- package/dist/generated/duel/errors/duel.js +35 -0
- package/dist/generated/duel/errors/index.d.ts +8 -0
- package/dist/generated/duel/errors/index.js +9 -0
- package/dist/generated/duel/index.d.ts +12 -0
- package/dist/generated/duel/index.js +13 -0
- package/dist/generated/duel/instructions/cancelTicket.d.ts +45 -0
- package/dist/generated/duel/instructions/cancelTicket.js +56 -0
- package/dist/generated/duel/instructions/closeTicket.d.ts +45 -0
- package/dist/generated/duel/instructions/closeTicket.js +56 -0
- package/dist/generated/duel/instructions/commitTickets.d.ts +39 -0
- package/dist/generated/duel/instructions/commitTickets.js +50 -0
- package/dist/generated/duel/instructions/createTicket.d.ts +48 -0
- package/dist/generated/duel/instructions/createTicket.js +63 -0
- package/dist/generated/duel/instructions/delegateQueue.d.ts +69 -0
- package/dist/generated/duel/instructions/delegateQueue.js +90 -0
- package/dist/generated/duel/instructions/delegateTicket.d.ts +69 -0
- package/dist/generated/duel/instructions/delegateTicket.js +90 -0
- package/dist/generated/duel/instructions/flushMatches.d.ts +37 -0
- package/dist/generated/duel/instructions/flushMatches.js +43 -0
- package/dist/generated/duel/instructions/index.d.ts +19 -0
- package/dist/generated/duel/instructions/index.js +20 -0
- package/dist/generated/duel/instructions/initializeQueue.d.ts +48 -0
- package/dist/generated/duel/instructions/initializeQueue.js +63 -0
- package/dist/generated/duel/instructions/initializeTenant.d.ts +70 -0
- package/dist/generated/duel/instructions/initializeTenant.js +67 -0
- package/dist/generated/duel/instructions/joinQueue.d.ts +51 -0
- package/dist/generated/duel/instructions/joinQueue.js +56 -0
- package/dist/generated/duel/instructions/processUndelegation.d.ts +43 -0
- package/dist/generated/duel/instructions/processUndelegation.js +49 -0
- package/dist/generated/duel/instructions/setupTicketPermission.d.ts +54 -0
- package/dist/generated/duel/instructions/setupTicketPermission.js +63 -0
- package/dist/generated/duel/programs/duel.d.ts +92 -0
- package/dist/generated/duel/programs/duel.js +146 -0
- package/dist/generated/duel/programs/index.d.ts +8 -0
- package/dist/generated/duel/programs/index.js +9 -0
- package/dist/generated/duel/types/accountType.d.ts +25 -0
- package/dist/generated/duel/types/accountType.js +25 -0
- package/dist/generated/duel/types/index.d.ts +13 -0
- package/dist/generated/duel/types/index.js +14 -0
- package/dist/generated/duel/types/matchEntry.d.ts +23 -0
- package/dist/generated/duel/types/matchEntry.js +18 -0
- package/dist/generated/duel/types/matchFound.d.ts +23 -0
- package/dist/generated/duel/types/matchFound.js +18 -0
- package/dist/generated/duel/types/pendingMatch.d.ts +21 -0
- package/dist/generated/duel/types/pendingMatch.js +18 -0
- package/dist/generated/duel/types/queueEntry.d.ts +19 -0
- package/dist/generated/duel/types/queueEntry.js +18 -0
- package/dist/generated/duel/types/ticketStatus.d.ts +40 -0
- package/dist/generated/duel/types/ticketStatus.js +25 -0
- package/dist/generated/rps-game/accounts/gameSession.d.ts +40 -0
- package/dist/generated/rps-game/accounts/gameSession.js +45 -0
- package/dist/generated/rps-game/accounts/index.d.ts +9 -0
- package/dist/generated/rps-game/accounts/index.js +10 -0
- package/dist/generated/rps-game/accounts/playerProfile.d.ts +36 -0
- package/dist/generated/rps-game/accounts/playerProfile.js +47 -0
- package/dist/generated/rps-game/errors/index.d.ts +8 -0
- package/dist/generated/rps-game/errors/index.js +9 -0
- package/dist/generated/rps-game/errors/rpsGame.d.ts +25 -0
- package/dist/generated/rps-game/errors/rpsGame.js +29 -0
- package/dist/generated/rps-game/index.d.ts +12 -0
- package/dist/generated/rps-game/index.js +13 -0
- package/dist/generated/rps-game/instructions/closePlayer.d.ts +45 -0
- package/dist/generated/rps-game/instructions/closePlayer.js +56 -0
- package/dist/generated/rps-game/instructions/delegatePda.d.ts +69 -0
- package/dist/generated/rps-game/instructions/delegatePda.js +90 -0
- package/dist/generated/rps-game/instructions/index.d.ts +16 -0
- package/dist/generated/rps-game/instructions/index.js +17 -0
- package/dist/generated/rps-game/instructions/initializePlayer.d.ts +48 -0
- package/dist/generated/rps-game/instructions/initializePlayer.js +63 -0
- package/dist/generated/rps-game/instructions/makeChoice.d.ts +44 -0
- package/dist/generated/rps-game/instructions/makeChoice.js +46 -0
- package/dist/generated/rps-game/instructions/onMatchFound.d.ts +43 -0
- package/dist/generated/rps-game/instructions/onMatchFound.js +45 -0
- package/dist/generated/rps-game/instructions/persistResults.d.ts +43 -0
- package/dist/generated/rps-game/instructions/persistResults.js +50 -0
- package/dist/generated/rps-game/instructions/processUndelegation.d.ts +43 -0
- package/dist/generated/rps-game/instructions/processUndelegation.js +49 -0
- package/dist/generated/rps-game/instructions/startGame.d.ts +54 -0
- package/dist/generated/rps-game/instructions/startGame.js +67 -0
- package/dist/generated/rps-game/instructions/startGameWithTicket.d.ts +57 -0
- package/dist/generated/rps-game/instructions/startGameWithTicket.js +67 -0
- package/dist/generated/rps-game/programs/index.d.ts +8 -0
- package/dist/generated/rps-game/programs/index.js +9 -0
- package/dist/generated/rps-game/programs/rpsGame.d.ts +78 -0
- package/dist/generated/rps-game/programs/rpsGame.js +118 -0
- package/dist/generated/rps-game/types/accountType.d.ts +34 -0
- package/dist/generated/rps-game/types/accountType.js +25 -0
- package/dist/generated/rps-game/types/choice.d.ts +17 -0
- package/dist/generated/rps-game/types/choice.js +25 -0
- package/dist/generated/rps-game/types/gameResult.d.ts +26 -0
- package/dist/generated/rps-game/types/gameResult.js +25 -0
- package/dist/generated/rps-game/types/index.d.ts +10 -0
- package/dist/generated/rps-game/types/index.js +11 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +3 -2
- package/dist/player.d.ts +25 -46
- package/dist/player.js +81 -140
- package/dist/tee.d.ts +14 -0
- package/dist/tee.js +62 -0
- package/dist/transaction.d.ts +11 -0
- package/dist/transaction.js +50 -0
- package/dist/utils.d.ts +4 -4
- package/dist/utils.js +23 -8
- package/package.json +3 -6
- package/src/admin.ts +151 -161
- package/src/duel.json +66 -7
- package/src/encryption.ts +0 -3
- package/src/generated/duel/accounts/index.ts +11 -0
- package/src/generated/duel/accounts/matchTicket.ts +77 -0
- package/src/generated/duel/accounts/queue.ts +77 -0
- package/src/generated/duel/accounts/tenant.ts +76 -0
- package/src/generated/duel/errors/duel.ts +46 -0
- package/src/generated/duel/errors/index.ts +9 -0
- package/src/generated/duel/index.ts +13 -0
- package/src/generated/duel/instructions/cancelTicket.ts +100 -0
- package/src/generated/duel/instructions/closeTicket.ts +100 -0
- package/src/generated/duel/instructions/commitTickets.ts +84 -0
- package/src/generated/duel/instructions/createTicket.ts +109 -0
- package/src/generated/duel/instructions/delegateQueue.ts +157 -0
- package/src/generated/duel/instructions/delegateTicket.ts +157 -0
- package/src/generated/duel/instructions/flushMatches.ts +76 -0
- package/src/generated/duel/instructions/index.ts +20 -0
- package/src/generated/duel/instructions/initializeQueue.ts +109 -0
- package/src/generated/duel/instructions/initializeTenant.ts +126 -0
- package/src/generated/duel/instructions/joinQueue.ts +106 -0
- package/src/generated/duel/instructions/processUndelegation.ts +86 -0
- package/src/generated/duel/instructions/setupTicketPermission.ts +115 -0
- package/src/generated/duel/programs/duel.ts +108 -0
- package/src/generated/duel/programs/index.ts +9 -0
- package/src/generated/duel/types/accountType.ts +36 -0
- package/src/generated/duel/types/index.ts +14 -0
- package/src/generated/duel/types/matchEntry.ts +25 -0
- package/src/generated/duel/types/matchFound.ts +25 -0
- package/src/generated/duel/types/pendingMatch.ts +25 -0
- package/src/generated/duel/types/queueEntry.ts +25 -0
- package/src/generated/duel/types/ticketStatus.ts +38 -0
- package/src/generated/rps-game/accounts/gameSession.ts +77 -0
- package/src/generated/rps-game/accounts/index.ts +10 -0
- package/src/generated/rps-game/accounts/playerProfile.ts +80 -0
- package/src/generated/rps-game/errors/index.ts +9 -0
- package/src/generated/rps-game/errors/rpsGame.ts +40 -0
- package/src/generated/rps-game/index.ts +13 -0
- package/src/generated/rps-game/instructions/closePlayer.ts +100 -0
- package/src/generated/rps-game/instructions/delegatePda.ts +157 -0
- package/src/generated/rps-game/instructions/index.ts +17 -0
- package/src/generated/rps-game/instructions/initializePlayer.ts +109 -0
- package/src/generated/rps-game/instructions/makeChoice.ts +84 -0
- package/src/generated/rps-game/instructions/onMatchFound.ts +79 -0
- package/src/generated/rps-game/instructions/persistResults.ts +88 -0
- package/src/generated/rps-game/instructions/processUndelegation.ts +86 -0
- package/src/generated/rps-game/instructions/startGame.ts +118 -0
- package/src/generated/rps-game/instructions/startGameWithTicket.ts +121 -0
- package/src/generated/rps-game/programs/index.ts +9 -0
- package/src/generated/rps-game/programs/rpsGame.ts +95 -0
- package/src/generated/rps-game/types/accountType.ts +36 -0
- package/src/generated/rps-game/types/choice.ts +25 -0
- package/src/generated/rps-game/types/gameResult.ts +37 -0
- package/src/generated/rps-game/types/index.ts +11 -0
- package/src/index.ts +2 -1
- package/src/player.ts +129 -192
- package/src/{idl/private_matchmaking.json → rps_game.json} +547 -583
- package/src/tee.ts +79 -0
- package/src/transaction.ts +90 -0
- package/src/utils.ts +35 -20
- package/tsconfig.json +2 -2
- package/dist/client.d.ts +0 -54
- package/dist/client.js +0 -265
- package/dist/duel.json +0 -1207
- package/dist/private_matchmaking.json +0 -534
- package/dist/types.d.ts +0 -635
- package/dist/types.js +0 -2
- package/src/idl/private_matchmaking.ts +0 -1033
- 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
|
|
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:
|
|
6
|
-
export declare function deriveTenantPda(programId:
|
|
7
|
-
export declare function deriveTicketPda(programId:
|
|
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
|
|
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] =
|
|
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] =
|
|
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] =
|
|
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,
|
|
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.
|
|
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
|
-
"@
|
|
19
|
-
"@
|
|
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
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
-
|
|
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?:
|
|
14
|
-
eloWindow?:
|
|
23
|
+
authority?: Address;
|
|
24
|
+
eloWindow?: bigint;
|
|
15
25
|
eloOffset?: number;
|
|
16
26
|
eloDataType?: EloDataType;
|
|
17
|
-
callbackProgramId?:
|
|
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
|
|
24
|
-
case
|
|
25
|
-
case
|
|
26
|
-
case
|
|
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
|
-
|
|
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
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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
|
-
|
|
47
|
-
return utils.
|
|
57
|
+
async getQueuePda(authority: Address): Promise<Address> {
|
|
58
|
+
return utils.deriveQueuePda(this.programId, authority);
|
|
48
59
|
}
|
|
49
60
|
|
|
50
|
-
|
|
51
|
-
return utils.
|
|
61
|
+
async getTenantPda(authority: Address): Promise<Address> {
|
|
62
|
+
return utils.deriveTenantPda(this.programId, authority);
|
|
52
63
|
}
|
|
53
64
|
|
|
54
|
-
|
|
55
|
-
|
|
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
|
-
|
|
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:
|
|
74
|
+
tenantProgramId: Address,
|
|
73
75
|
options?: InitializeTenantOptions,
|
|
74
|
-
|
|
75
|
-
signers: web3.Keypair[] = []
|
|
76
|
-
): Promise<web3.TransactionSignature> {
|
|
76
|
+
): Promise<string> {
|
|
77
77
|
const {
|
|
78
|
-
|
|
79
|
-
eloWindow = 100,
|
|
78
|
+
eloWindow = 100n,
|
|
80
79
|
eloOffset = 40,
|
|
81
|
-
eloDataType =
|
|
80
|
+
eloDataType = "u16",
|
|
82
81
|
callbackProgramId = null,
|
|
83
82
|
callbackDiscriminator = null,
|
|
84
83
|
} = options || {};
|
|
85
84
|
|
|
86
85
|
const eloSize = getEloSize(eloDataType);
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
-
|
|
111
|
-
tenant:
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
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:
|
|
132
|
-
validator
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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:
|
|
154
|
-
tenant:
|
|
155
|
-
ticketPdas:
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
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
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
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
|
-
*
|
|
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
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
): Promise<
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
.
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
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
|
}
|