@1upmonster/duel 0.2.1 → 0.2.3
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 +120 -59
- package/dist/admin.d.ts +8 -1
- package/dist/admin.js +52 -9
- package/dist/generated/duel/errors/duel.d.ts +1 -3
- package/dist/generated/duel/errors/duel.js +2 -4
- package/dist/generated/duel/instructions/index.d.ts +2 -0
- package/dist/generated/duel/instructions/index.js +3 -1
- package/dist/generated/duel/instructions/joinQueue.d.ts +1 -1
- package/dist/generated/duel/instructions/joinQueue.js +3 -3
- package/dist/generated/duel/instructions/setupQueuePermission.d.ts +51 -0
- package/dist/generated/duel/instructions/setupQueuePermission.js +63 -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 +11 -3
- package/dist/generated/duel/programs/duel.js +19 -3
- package/dist/player.d.ts +8 -1
- package/dist/player.js +56 -5
- package/dist/tee.d.ts +4 -3
- package/dist/tee.js +17 -23
- package/dist/transaction.d.ts +2 -0
- package/dist/transaction.js +30 -19
- package/dist/utils.d.ts +10 -0
- package/dist/utils.js +28 -1
- package/package.json +1 -1
- package/src/admin.ts +67 -7
- package/src/duel.json +57 -5
- package/src/generated/duel/errors/duel.ts +2 -4
- package/src/generated/duel/instructions/index.ts +3 -1
- package/src/generated/duel/instructions/joinQueue.ts +3 -3
- package/src/generated/duel/instructions/setupQueuePermission.ts +112 -0
- package/src/generated/duel/instructions/setupTicketPermission.ts +115 -0
- package/src/generated/duel/programs/duel.ts +12 -4
- package/src/player.ts +72 -1
- package/src/tee.ts +18 -22
- package/src/transaction.ts +33 -18
- package/src/utils.ts +34 -0
- package/src/encryption.ts +0 -154
- package/src/idl/private_matchmaking.json +0 -1027
- package/src/idl/private_matchmaking.ts +0 -1033
package/src/duel.json
CHANGED
|
@@ -832,6 +832,63 @@
|
|
|
832
832
|
}
|
|
833
833
|
]
|
|
834
834
|
},
|
|
835
|
+
{
|
|
836
|
+
"name": "setup_queue_permission",
|
|
837
|
+
"docs": [
|
|
838
|
+
"Set up permission for queue PDA so only the authority can read it on TEE.",
|
|
839
|
+
"Must be called BEFORE delegate_queue while the program still owns the PDA."
|
|
840
|
+
],
|
|
841
|
+
"discriminator": [
|
|
842
|
+
223,
|
|
843
|
+
132,
|
|
844
|
+
77,
|
|
845
|
+
15,
|
|
846
|
+
224,
|
|
847
|
+
155,
|
|
848
|
+
125,
|
|
849
|
+
224
|
|
850
|
+
],
|
|
851
|
+
"accounts": [
|
|
852
|
+
{
|
|
853
|
+
"name": "queue",
|
|
854
|
+
"pda": {
|
|
855
|
+
"seeds": [
|
|
856
|
+
{
|
|
857
|
+
"kind": "const",
|
|
858
|
+
"value": [
|
|
859
|
+
113,
|
|
860
|
+
117,
|
|
861
|
+
101,
|
|
862
|
+
117,
|
|
863
|
+
101
|
|
864
|
+
]
|
|
865
|
+
},
|
|
866
|
+
{
|
|
867
|
+
"kind": "account",
|
|
868
|
+
"path": "authority"
|
|
869
|
+
}
|
|
870
|
+
]
|
|
871
|
+
}
|
|
872
|
+
},
|
|
873
|
+
{
|
|
874
|
+
"name": "authority",
|
|
875
|
+
"writable": true,
|
|
876
|
+
"signer": true
|
|
877
|
+
},
|
|
878
|
+
{
|
|
879
|
+
"name": "permission",
|
|
880
|
+
"writable": true
|
|
881
|
+
},
|
|
882
|
+
{
|
|
883
|
+
"name": "permission_program"
|
|
884
|
+
},
|
|
885
|
+
{
|
|
886
|
+
"name": "system_program",
|
|
887
|
+
"address": "11111111111111111111111111111111"
|
|
888
|
+
}
|
|
889
|
+
],
|
|
890
|
+
"args": []
|
|
891
|
+
},
|
|
835
892
|
{
|
|
836
893
|
"name": "setup_ticket_permission",
|
|
837
894
|
"docs": [
|
|
@@ -984,11 +1041,6 @@
|
|
|
984
1041
|
"code": 6005,
|
|
985
1042
|
"name": "InvalidTicketAccount",
|
|
986
1043
|
"msg": "Invalid ticket account"
|
|
987
|
-
},
|
|
988
|
-
{
|
|
989
|
-
"code": 6006,
|
|
990
|
-
"name": "MissingCallbackProgram",
|
|
991
|
-
"msg": "Missing or invalid callback program in remaining accounts"
|
|
992
1044
|
}
|
|
993
1045
|
],
|
|
994
1046
|
"types": [
|
|
@@ -21,14 +21,12 @@ export const DUEL_ERROR__INVALID_ELO_SIZE = 0x1773; // 6003
|
|
|
21
21
|
export const DUEL_ERROR__INVALID_TICKET_STATUS = 0x1774; // 6004
|
|
22
22
|
/** InvalidTicketAccount: Invalid ticket account */
|
|
23
23
|
export const DUEL_ERROR__INVALID_TICKET_ACCOUNT = 0x1775; // 6005
|
|
24
|
-
/** MissingCallbackProgram: Missing or invalid callback program in remaining accounts */
|
|
25
|
-
export const DUEL_ERROR__MISSING_CALLBACK_PROGRAM = 0x1776; // 6006
|
|
26
24
|
|
|
27
|
-
export type DuelError = typeof DUEL_ERROR__DATA_TOO_SMALL | typeof DUEL_ERROR__INVALID_ELO_SIZE | typeof DUEL_ERROR__INVALID_TENANT | typeof DUEL_ERROR__INVALID_TICKET_ACCOUNT | typeof DUEL_ERROR__INVALID_TICKET_STATUS | typeof
|
|
25
|
+
export type DuelError = typeof DUEL_ERROR__DATA_TOO_SMALL | typeof DUEL_ERROR__INVALID_ELO_SIZE | typeof DUEL_ERROR__INVALID_TENANT | typeof DUEL_ERROR__INVALID_TICKET_ACCOUNT | typeof DUEL_ERROR__INVALID_TICKET_STATUS | typeof DUEL_ERROR__UNAUTHORIZED;
|
|
28
26
|
|
|
29
27
|
let duelErrorMessages: Record<DuelError, string> | undefined;
|
|
30
28
|
if (process.env.NODE_ENV !== 'production') {
|
|
31
|
-
duelErrorMessages = { [DUEL_ERROR__DATA_TOO_SMALL]: `Account data too small for ELO read`, [DUEL_ERROR__INVALID_ELO_SIZE]: `Invalid ELO size (must be 1, 2, 4, or 8 bytes)`, [DUEL_ERROR__INVALID_TENANT]: `Account does not belong to the specified Tenant Program`, [DUEL_ERROR__INVALID_TICKET_ACCOUNT]: `Invalid ticket account`, [DUEL_ERROR__INVALID_TICKET_STATUS]: `Invalid ticket status for this operation`, [
|
|
29
|
+
duelErrorMessages = { [DUEL_ERROR__DATA_TOO_SMALL]: `Account data too small for ELO read`, [DUEL_ERROR__INVALID_ELO_SIZE]: `Invalid ELO size (must be 1, 2, 4, or 8 bytes)`, [DUEL_ERROR__INVALID_TENANT]: `Account does not belong to the specified Tenant Program`, [DUEL_ERROR__INVALID_TICKET_ACCOUNT]: `Invalid ticket account`, [DUEL_ERROR__INVALID_TICKET_STATUS]: `Invalid ticket status for this operation`, [DUEL_ERROR__UNAUTHORIZED]: `Unauthorized access` };
|
|
32
30
|
}
|
|
33
31
|
|
|
34
32
|
export function getDuelErrorMessage(code: DuelError): string {
|
|
@@ -16,4 +16,6 @@ export * from './flushMatches';
|
|
|
16
16
|
export * from './initializeQueue';
|
|
17
17
|
export * from './initializeTenant';
|
|
18
18
|
export * from './joinQueue';
|
|
19
|
-
export * from './processUndelegation';
|
|
19
|
+
export * from './processUndelegation';
|
|
20
|
+
export * from './setupQueuePermission';
|
|
21
|
+
export * from './setupTicketPermission';
|
|
@@ -15,7 +15,7 @@ export const JOIN_QUEUE_DISCRIMINATOR = new Uint8Array([157, 115, 48, 109, 65, 8
|
|
|
15
15
|
export function getJoinQueueDiscriminatorBytes() { return fixEncoderSize(getBytesEncoder(), 8).encode(JOIN_QUEUE_DISCRIMINATOR); }
|
|
16
16
|
|
|
17
17
|
export type JoinQueueInstruction<TProgram extends string = typeof DUEL_PROGRAM_ADDRESS, TAccountQueue extends string | AccountMeta<string> = string, TAccountTenant extends string | AccountMeta<string> = string, TAccountPlayerData extends string | AccountMeta<string> = string, TAccountPlayerTicket extends string | AccountMeta<string> = string, TAccountSigner extends string | AccountMeta<string> = string, TRemainingAccounts extends readonly AccountMeta<string>[] = []> =
|
|
18
|
-
Instruction<TProgram> & InstructionWithData<ReadonlyUint8Array> & InstructionWithAccounts<[TAccountQueue extends string ? WritableAccount<TAccountQueue> : TAccountQueue, TAccountTenant extends string ? ReadonlyAccount<TAccountTenant> : TAccountTenant, TAccountPlayerData extends string ?
|
|
18
|
+
Instruction<TProgram> & InstructionWithData<ReadonlyUint8Array> & InstructionWithAccounts<[TAccountQueue extends string ? WritableAccount<TAccountQueue> : TAccountQueue, TAccountTenant extends string ? ReadonlyAccount<TAccountTenant> : TAccountTenant, TAccountPlayerData extends string ? ReadonlyAccount<TAccountPlayerData> : TAccountPlayerData, TAccountPlayerTicket extends string ? WritableAccount<TAccountPlayerTicket> : TAccountPlayerTicket, TAccountSigner extends string ? ReadonlySignerAccount<TAccountSigner> & AccountSignerMeta<TAccountSigner> : TAccountSigner, ...TRemainingAccounts]>;
|
|
19
19
|
|
|
20
20
|
export type JoinQueueInstructionData = { discriminator: ReadonlyUint8Array; };
|
|
21
21
|
|
|
@@ -46,7 +46,7 @@ export async function getJoinQueueInstructionAsync<TAccountQueue extends string,
|
|
|
46
46
|
const programAddress = config?.programAddress ?? DUEL_PROGRAM_ADDRESS;
|
|
47
47
|
|
|
48
48
|
// Original accounts.
|
|
49
|
-
const originalAccounts = { queue: { value: input.queue ?? null, isWritable: true }, tenant: { value: input.tenant ?? null, isWritable: false }, playerData: { value: input.playerData ?? null, isWritable:
|
|
49
|
+
const originalAccounts = { queue: { value: input.queue ?? null, isWritable: true }, tenant: { value: input.tenant ?? null, isWritable: false }, playerData: { value: input.playerData ?? null, isWritable: false }, playerTicket: { value: input.playerTicket ?? null, isWritable: true }, signer: { value: input.signer ?? null, isWritable: false } }
|
|
50
50
|
const accounts = originalAccounts as Record<keyof typeof originalAccounts, ResolvedInstructionAccount>;
|
|
51
51
|
|
|
52
52
|
|
|
@@ -72,7 +72,7 @@ export function getJoinQueueInstruction<TAccountQueue extends string, TAccountTe
|
|
|
72
72
|
const programAddress = config?.programAddress ?? DUEL_PROGRAM_ADDRESS;
|
|
73
73
|
|
|
74
74
|
// Original accounts.
|
|
75
|
-
const originalAccounts = { queue: { value: input.queue ?? null, isWritable: true }, tenant: { value: input.tenant ?? null, isWritable: false }, playerData: { value: input.playerData ?? null, isWritable:
|
|
75
|
+
const originalAccounts = { queue: { value: input.queue ?? null, isWritable: true }, tenant: { value: input.tenant ?? null, isWritable: false }, playerData: { value: input.playerData ?? null, isWritable: false }, playerTicket: { value: input.playerTicket ?? null, isWritable: true }, signer: { value: input.signer ?? null, isWritable: false } }
|
|
76
76
|
const accounts = originalAccounts as Record<keyof typeof originalAccounts, ResolvedInstructionAccount>;
|
|
77
77
|
|
|
78
78
|
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This code was AUTOGENERATED using the Codama library.
|
|
3
|
+
* Please DO NOT EDIT THIS FILE, instead use visitors
|
|
4
|
+
* to add features, then rerun Codama to update it.
|
|
5
|
+
*
|
|
6
|
+
* @see https://github.com/codama-idl/codama
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { combineCodec, fixDecoderSize, fixEncoderSize, getAddressEncoder, getBytesDecoder, getBytesEncoder, getProgramDerivedAddress, getStructDecoder, getStructEncoder, SOLANA_ERROR__PROGRAM_CLIENTS__INSUFFICIENT_ACCOUNT_METAS, SolanaError, transformEncoder, type AccountMeta, type AccountSignerMeta, type Address, type FixedSizeCodec, type FixedSizeDecoder, type FixedSizeEncoder, type Instruction, type InstructionWithAccounts, type InstructionWithData, type ReadonlyAccount, type ReadonlyUint8Array, type TransactionSigner, type WritableAccount, type WritableSignerAccount } from '@solana/kit';
|
|
10
|
+
import { getAccountMetaFactory, getAddressFromResolvedInstructionAccount, type ResolvedInstructionAccount } from '@solana/program-client-core';
|
|
11
|
+
import { DUEL_PROGRAM_ADDRESS } from '../programs';
|
|
12
|
+
|
|
13
|
+
export const SETUP_QUEUE_PERMISSION_DISCRIMINATOR = new Uint8Array([223, 132, 77, 15, 224, 155, 125, 224]);
|
|
14
|
+
|
|
15
|
+
export function getSetupQueuePermissionDiscriminatorBytes() { return fixEncoderSize(getBytesEncoder(), 8).encode(SETUP_QUEUE_PERMISSION_DISCRIMINATOR); }
|
|
16
|
+
|
|
17
|
+
export type SetupQueuePermissionInstruction<TProgram extends string = typeof DUEL_PROGRAM_ADDRESS, TAccountQueue extends string | AccountMeta<string> = string, TAccountAuthority extends string | AccountMeta<string> = string, TAccountPermission extends string | AccountMeta<string> = string, TAccountPermissionProgram extends string | AccountMeta<string> = string, TAccountSystemProgram extends string | AccountMeta<string> = "11111111111111111111111111111111", TRemainingAccounts extends readonly AccountMeta<string>[] = []> =
|
|
18
|
+
Instruction<TProgram> & InstructionWithData<ReadonlyUint8Array> & InstructionWithAccounts<[TAccountQueue extends string ? ReadonlyAccount<TAccountQueue> : TAccountQueue, TAccountAuthority extends string ? WritableSignerAccount<TAccountAuthority> & AccountSignerMeta<TAccountAuthority> : TAccountAuthority, TAccountPermission extends string ? WritableAccount<TAccountPermission> : TAccountPermission, TAccountPermissionProgram extends string ? ReadonlyAccount<TAccountPermissionProgram> : TAccountPermissionProgram, TAccountSystemProgram extends string ? ReadonlyAccount<TAccountSystemProgram> : TAccountSystemProgram, ...TRemainingAccounts]>;
|
|
19
|
+
|
|
20
|
+
export type SetupQueuePermissionInstructionData = { discriminator: ReadonlyUint8Array; };
|
|
21
|
+
|
|
22
|
+
export type SetupQueuePermissionInstructionDataArgs = { };
|
|
23
|
+
|
|
24
|
+
export function getSetupQueuePermissionInstructionDataEncoder(): FixedSizeEncoder<SetupQueuePermissionInstructionDataArgs> {
|
|
25
|
+
return transformEncoder(getStructEncoder([['discriminator', fixEncoderSize(getBytesEncoder(), 8)]]), (value) => ({ ...value, discriminator: SETUP_QUEUE_PERMISSION_DISCRIMINATOR }));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function getSetupQueuePermissionInstructionDataDecoder(): FixedSizeDecoder<SetupQueuePermissionInstructionData> {
|
|
29
|
+
return getStructDecoder([['discriminator', fixDecoderSize(getBytesDecoder(), 8)]]);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function getSetupQueuePermissionInstructionDataCodec(): FixedSizeCodec<SetupQueuePermissionInstructionDataArgs, SetupQueuePermissionInstructionData> {
|
|
33
|
+
return combineCodec(getSetupQueuePermissionInstructionDataEncoder(), getSetupQueuePermissionInstructionDataDecoder());
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export type SetupQueuePermissionAsyncInput<TAccountQueue extends string = string, TAccountAuthority extends string = string, TAccountPermission extends string = string, TAccountPermissionProgram extends string = string, TAccountSystemProgram extends string = string> = {
|
|
37
|
+
queue?: Address<TAccountQueue>;
|
|
38
|
+
authority: TransactionSigner<TAccountAuthority>;
|
|
39
|
+
permission: Address<TAccountPermission>;
|
|
40
|
+
permissionProgram: Address<TAccountPermissionProgram>;
|
|
41
|
+
systemProgram?: Address<TAccountSystemProgram>;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export async function getSetupQueuePermissionInstructionAsync<TAccountQueue extends string, TAccountAuthority extends string, TAccountPermission extends string, TAccountPermissionProgram extends string, TAccountSystemProgram extends string, TProgramAddress extends Address = typeof DUEL_PROGRAM_ADDRESS>(input: SetupQueuePermissionAsyncInput<TAccountQueue, TAccountAuthority, TAccountPermission, TAccountPermissionProgram, TAccountSystemProgram>, config?: { programAddress?: TProgramAddress } ): Promise<SetupQueuePermissionInstruction<TProgramAddress, TAccountQueue, TAccountAuthority, TAccountPermission, TAccountPermissionProgram, TAccountSystemProgram>> {
|
|
45
|
+
// Program address.
|
|
46
|
+
const programAddress = config?.programAddress ?? DUEL_PROGRAM_ADDRESS;
|
|
47
|
+
|
|
48
|
+
// Original accounts.
|
|
49
|
+
const originalAccounts = { queue: { value: input.queue ?? null, isWritable: false }, authority: { value: input.authority ?? null, isWritable: true }, permission: { value: input.permission ?? null, isWritable: true }, permissionProgram: { value: input.permissionProgram ?? null, isWritable: false }, systemProgram: { value: input.systemProgram ?? null, isWritable: false } }
|
|
50
|
+
const accounts = originalAccounts as Record<keyof typeof originalAccounts, ResolvedInstructionAccount>;
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
// Resolve default values.
|
|
54
|
+
if (!accounts.queue.value) {
|
|
55
|
+
accounts.queue.value = await getProgramDerivedAddress({ programAddress, seeds: [getBytesEncoder().encode(new Uint8Array([113, 117, 101, 117, 101])), getAddressEncoder().encode(getAddressFromResolvedInstructionAccount("authority", accounts.authority.value))] });
|
|
56
|
+
}
|
|
57
|
+
if (!accounts.systemProgram.value) {
|
|
58
|
+
accounts.systemProgram.value = '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const getAccountMeta = getAccountMetaFactory(programAddress, 'programId');
|
|
62
|
+
return Object.freeze({ accounts: [getAccountMeta("queue", accounts.queue), getAccountMeta("authority", accounts.authority), getAccountMeta("permission", accounts.permission), getAccountMeta("permissionProgram", accounts.permissionProgram), getAccountMeta("systemProgram", accounts.systemProgram)], data: getSetupQueuePermissionInstructionDataEncoder().encode({}), programAddress } as SetupQueuePermissionInstruction<TProgramAddress, TAccountQueue, TAccountAuthority, TAccountPermission, TAccountPermissionProgram, TAccountSystemProgram>);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export type SetupQueuePermissionInput<TAccountQueue extends string = string, TAccountAuthority extends string = string, TAccountPermission extends string = string, TAccountPermissionProgram extends string = string, TAccountSystemProgram extends string = string> = {
|
|
66
|
+
queue: Address<TAccountQueue>;
|
|
67
|
+
authority: TransactionSigner<TAccountAuthority>;
|
|
68
|
+
permission: Address<TAccountPermission>;
|
|
69
|
+
permissionProgram: Address<TAccountPermissionProgram>;
|
|
70
|
+
systemProgram?: Address<TAccountSystemProgram>;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function getSetupQueuePermissionInstruction<TAccountQueue extends string, TAccountAuthority extends string, TAccountPermission extends string, TAccountPermissionProgram extends string, TAccountSystemProgram extends string, TProgramAddress extends Address = typeof DUEL_PROGRAM_ADDRESS>(input: SetupQueuePermissionInput<TAccountQueue, TAccountAuthority, TAccountPermission, TAccountPermissionProgram, TAccountSystemProgram>, config?: { programAddress?: TProgramAddress } ): SetupQueuePermissionInstruction<TProgramAddress, TAccountQueue, TAccountAuthority, TAccountPermission, TAccountPermissionProgram, TAccountSystemProgram> {
|
|
74
|
+
// Program address.
|
|
75
|
+
const programAddress = config?.programAddress ?? DUEL_PROGRAM_ADDRESS;
|
|
76
|
+
|
|
77
|
+
// Original accounts.
|
|
78
|
+
const originalAccounts = { queue: { value: input.queue ?? null, isWritable: false }, authority: { value: input.authority ?? null, isWritable: true }, permission: { value: input.permission ?? null, isWritable: true }, permissionProgram: { value: input.permissionProgram ?? null, isWritable: false }, systemProgram: { value: input.systemProgram ?? null, isWritable: false } }
|
|
79
|
+
const accounts = originalAccounts as Record<keyof typeof originalAccounts, ResolvedInstructionAccount>;
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
// Resolve default values.
|
|
83
|
+
if (!accounts.systemProgram.value) {
|
|
84
|
+
accounts.systemProgram.value = '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const getAccountMeta = getAccountMetaFactory(programAddress, 'programId');
|
|
88
|
+
return Object.freeze({ accounts: [getAccountMeta("queue", accounts.queue), getAccountMeta("authority", accounts.authority), getAccountMeta("permission", accounts.permission), getAccountMeta("permissionProgram", accounts.permissionProgram), getAccountMeta("systemProgram", accounts.systemProgram)], data: getSetupQueuePermissionInstructionDataEncoder().encode({}), programAddress } as SetupQueuePermissionInstruction<TProgramAddress, TAccountQueue, TAccountAuthority, TAccountPermission, TAccountPermissionProgram, TAccountSystemProgram>);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export type ParsedSetupQueuePermissionInstruction<TProgram extends string = typeof DUEL_PROGRAM_ADDRESS, TAccountMetas extends readonly AccountMeta[] = readonly AccountMeta[]> = { programAddress: Address<TProgram>;
|
|
92
|
+
accounts: {
|
|
93
|
+
queue: TAccountMetas[0];
|
|
94
|
+
authority: TAccountMetas[1];
|
|
95
|
+
permission: TAccountMetas[2];
|
|
96
|
+
permissionProgram: TAccountMetas[3];
|
|
97
|
+
systemProgram: TAccountMetas[4];
|
|
98
|
+
};
|
|
99
|
+
data: SetupQueuePermissionInstructionData; };
|
|
100
|
+
|
|
101
|
+
export function parseSetupQueuePermissionInstruction<TProgram extends string, TAccountMetas extends readonly AccountMeta[]>(instruction: Instruction<TProgram> & InstructionWithAccounts<TAccountMetas> & InstructionWithData<ReadonlyUint8Array>): ParsedSetupQueuePermissionInstruction<TProgram, TAccountMetas> {
|
|
102
|
+
if (instruction.accounts.length < 5) {
|
|
103
|
+
throw new SolanaError(SOLANA_ERROR__PROGRAM_CLIENTS__INSUFFICIENT_ACCOUNT_METAS, { actualAccountMetas: instruction.accounts.length, expectedAccountMetas: 5 });
|
|
104
|
+
}
|
|
105
|
+
let accountIndex = 0;
|
|
106
|
+
const getNextAccount = () => {
|
|
107
|
+
const accountMeta = (instruction.accounts as TAccountMetas)[accountIndex]!;
|
|
108
|
+
accountIndex += 1;
|
|
109
|
+
return accountMeta;
|
|
110
|
+
}
|
|
111
|
+
return { programAddress: instruction.programAddress, accounts: { queue: getNextAccount(), authority: getNextAccount(), permission: getNextAccount(), permissionProgram: getNextAccount(), systemProgram: getNextAccount() }, data: getSetupQueuePermissionInstructionDataDecoder().decode(instruction.data) };
|
|
112
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This code was AUTOGENERATED using the Codama library.
|
|
3
|
+
* Please DO NOT EDIT THIS FILE, instead use visitors
|
|
4
|
+
* to add features, then rerun Codama to update it.
|
|
5
|
+
*
|
|
6
|
+
* @see https://github.com/codama-idl/codama
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { combineCodec, fixDecoderSize, fixEncoderSize, getAddressEncoder, getBytesDecoder, getBytesEncoder, getProgramDerivedAddress, getStructDecoder, getStructEncoder, SOLANA_ERROR__PROGRAM_CLIENTS__INSUFFICIENT_ACCOUNT_METAS, SolanaError, transformEncoder, type AccountMeta, type AccountSignerMeta, type Address, type FixedSizeCodec, type FixedSizeDecoder, type FixedSizeEncoder, type Instruction, type InstructionWithAccounts, type InstructionWithData, type ReadonlyAccount, type ReadonlyUint8Array, type TransactionSigner, type WritableAccount, type WritableSignerAccount } from '@solana/kit';
|
|
10
|
+
import { getAccountMetaFactory, getAddressFromResolvedInstructionAccount, type ResolvedInstructionAccount } from '@solana/program-client-core';
|
|
11
|
+
import { DUEL_PROGRAM_ADDRESS } from '../programs';
|
|
12
|
+
|
|
13
|
+
export const SETUP_TICKET_PERMISSION_DISCRIMINATOR = new Uint8Array([164, 29, 7, 235, 183, 223, 11, 85]);
|
|
14
|
+
|
|
15
|
+
export function getSetupTicketPermissionDiscriminatorBytes() { return fixEncoderSize(getBytesEncoder(), 8).encode(SETUP_TICKET_PERMISSION_DISCRIMINATOR); }
|
|
16
|
+
|
|
17
|
+
export type SetupTicketPermissionInstruction<TProgram extends string = typeof DUEL_PROGRAM_ADDRESS, TAccountTicket extends string | AccountMeta<string> = string, TAccountTenant extends string | AccountMeta<string> = string, TAccountPlayer extends string | AccountMeta<string> = string, TAccountPermission extends string | AccountMeta<string> = string, TAccountPermissionProgram extends string | AccountMeta<string> = string, TAccountSystemProgram extends string | AccountMeta<string> = "11111111111111111111111111111111", TRemainingAccounts extends readonly AccountMeta<string>[] = []> =
|
|
18
|
+
Instruction<TProgram> & InstructionWithData<ReadonlyUint8Array> & InstructionWithAccounts<[TAccountTicket extends string ? ReadonlyAccount<TAccountTicket> : TAccountTicket, TAccountTenant extends string ? ReadonlyAccount<TAccountTenant> : TAccountTenant, TAccountPlayer extends string ? WritableSignerAccount<TAccountPlayer> & AccountSignerMeta<TAccountPlayer> : TAccountPlayer, TAccountPermission extends string ? WritableAccount<TAccountPermission> : TAccountPermission, TAccountPermissionProgram extends string ? ReadonlyAccount<TAccountPermissionProgram> : TAccountPermissionProgram, TAccountSystemProgram extends string ? ReadonlyAccount<TAccountSystemProgram> : TAccountSystemProgram, ...TRemainingAccounts]>;
|
|
19
|
+
|
|
20
|
+
export type SetupTicketPermissionInstructionData = { discriminator: ReadonlyUint8Array; };
|
|
21
|
+
|
|
22
|
+
export type SetupTicketPermissionInstructionDataArgs = { };
|
|
23
|
+
|
|
24
|
+
export function getSetupTicketPermissionInstructionDataEncoder(): FixedSizeEncoder<SetupTicketPermissionInstructionDataArgs> {
|
|
25
|
+
return transformEncoder(getStructEncoder([['discriminator', fixEncoderSize(getBytesEncoder(), 8)]]), (value) => ({ ...value, discriminator: SETUP_TICKET_PERMISSION_DISCRIMINATOR }));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function getSetupTicketPermissionInstructionDataDecoder(): FixedSizeDecoder<SetupTicketPermissionInstructionData> {
|
|
29
|
+
return getStructDecoder([['discriminator', fixDecoderSize(getBytesDecoder(), 8)]]);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function getSetupTicketPermissionInstructionDataCodec(): FixedSizeCodec<SetupTicketPermissionInstructionDataArgs, SetupTicketPermissionInstructionData> {
|
|
33
|
+
return combineCodec(getSetupTicketPermissionInstructionDataEncoder(), getSetupTicketPermissionInstructionDataDecoder());
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export type SetupTicketPermissionAsyncInput<TAccountTicket extends string = string, TAccountTenant extends string = string, TAccountPlayer extends string = string, TAccountPermission extends string = string, TAccountPermissionProgram extends string = string, TAccountSystemProgram extends string = string> = {
|
|
37
|
+
ticket?: Address<TAccountTicket>;
|
|
38
|
+
tenant: Address<TAccountTenant>;
|
|
39
|
+
player: TransactionSigner<TAccountPlayer>;
|
|
40
|
+
permission: Address<TAccountPermission>;
|
|
41
|
+
permissionProgram: Address<TAccountPermissionProgram>;
|
|
42
|
+
systemProgram?: Address<TAccountSystemProgram>;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export async function getSetupTicketPermissionInstructionAsync<TAccountTicket extends string, TAccountTenant extends string, TAccountPlayer extends string, TAccountPermission extends string, TAccountPermissionProgram extends string, TAccountSystemProgram extends string, TProgramAddress extends Address = typeof DUEL_PROGRAM_ADDRESS>(input: SetupTicketPermissionAsyncInput<TAccountTicket, TAccountTenant, TAccountPlayer, TAccountPermission, TAccountPermissionProgram, TAccountSystemProgram>, config?: { programAddress?: TProgramAddress } ): Promise<SetupTicketPermissionInstruction<TProgramAddress, TAccountTicket, TAccountTenant, TAccountPlayer, TAccountPermission, TAccountPermissionProgram, TAccountSystemProgram>> {
|
|
46
|
+
// Program address.
|
|
47
|
+
const programAddress = config?.programAddress ?? DUEL_PROGRAM_ADDRESS;
|
|
48
|
+
|
|
49
|
+
// Original accounts.
|
|
50
|
+
const originalAccounts = { ticket: { value: input.ticket ?? null, isWritable: false }, tenant: { value: input.tenant ?? null, isWritable: false }, player: { value: input.player ?? null, isWritable: true }, permission: { value: input.permission ?? null, isWritable: true }, permissionProgram: { value: input.permissionProgram ?? null, isWritable: false }, systemProgram: { value: input.systemProgram ?? null, isWritable: false } }
|
|
51
|
+
const accounts = originalAccounts as Record<keyof typeof originalAccounts, ResolvedInstructionAccount>;
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
// Resolve default values.
|
|
55
|
+
if (!accounts.ticket.value) {
|
|
56
|
+
accounts.ticket.value = await getProgramDerivedAddress({ programAddress, seeds: [getBytesEncoder().encode(new Uint8Array([116, 105, 99, 107, 101, 116])), getAddressEncoder().encode(getAddressFromResolvedInstructionAccount("player", accounts.player.value)), getAddressEncoder().encode(getAddressFromResolvedInstructionAccount("tenant", accounts.tenant.value))] });
|
|
57
|
+
}
|
|
58
|
+
if (!accounts.systemProgram.value) {
|
|
59
|
+
accounts.systemProgram.value = '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const getAccountMeta = getAccountMetaFactory(programAddress, 'programId');
|
|
63
|
+
return Object.freeze({ accounts: [getAccountMeta("ticket", accounts.ticket), getAccountMeta("tenant", accounts.tenant), getAccountMeta("player", accounts.player), getAccountMeta("permission", accounts.permission), getAccountMeta("permissionProgram", accounts.permissionProgram), getAccountMeta("systemProgram", accounts.systemProgram)], data: getSetupTicketPermissionInstructionDataEncoder().encode({}), programAddress } as SetupTicketPermissionInstruction<TProgramAddress, TAccountTicket, TAccountTenant, TAccountPlayer, TAccountPermission, TAccountPermissionProgram, TAccountSystemProgram>);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export type SetupTicketPermissionInput<TAccountTicket extends string = string, TAccountTenant extends string = string, TAccountPlayer extends string = string, TAccountPermission extends string = string, TAccountPermissionProgram extends string = string, TAccountSystemProgram extends string = string> = {
|
|
67
|
+
ticket: Address<TAccountTicket>;
|
|
68
|
+
tenant: Address<TAccountTenant>;
|
|
69
|
+
player: TransactionSigner<TAccountPlayer>;
|
|
70
|
+
permission: Address<TAccountPermission>;
|
|
71
|
+
permissionProgram: Address<TAccountPermissionProgram>;
|
|
72
|
+
systemProgram?: Address<TAccountSystemProgram>;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function getSetupTicketPermissionInstruction<TAccountTicket extends string, TAccountTenant extends string, TAccountPlayer extends string, TAccountPermission extends string, TAccountPermissionProgram extends string, TAccountSystemProgram extends string, TProgramAddress extends Address = typeof DUEL_PROGRAM_ADDRESS>(input: SetupTicketPermissionInput<TAccountTicket, TAccountTenant, TAccountPlayer, TAccountPermission, TAccountPermissionProgram, TAccountSystemProgram>, config?: { programAddress?: TProgramAddress } ): SetupTicketPermissionInstruction<TProgramAddress, TAccountTicket, TAccountTenant, TAccountPlayer, TAccountPermission, TAccountPermissionProgram, TAccountSystemProgram> {
|
|
76
|
+
// Program address.
|
|
77
|
+
const programAddress = config?.programAddress ?? DUEL_PROGRAM_ADDRESS;
|
|
78
|
+
|
|
79
|
+
// Original accounts.
|
|
80
|
+
const originalAccounts = { ticket: { value: input.ticket ?? null, isWritable: false }, tenant: { value: input.tenant ?? null, isWritable: false }, player: { value: input.player ?? null, isWritable: true }, permission: { value: input.permission ?? null, isWritable: true }, permissionProgram: { value: input.permissionProgram ?? null, isWritable: false }, systemProgram: { value: input.systemProgram ?? null, isWritable: false } }
|
|
81
|
+
const accounts = originalAccounts as Record<keyof typeof originalAccounts, ResolvedInstructionAccount>;
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
// Resolve default values.
|
|
85
|
+
if (!accounts.systemProgram.value) {
|
|
86
|
+
accounts.systemProgram.value = '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const getAccountMeta = getAccountMetaFactory(programAddress, 'programId');
|
|
90
|
+
return Object.freeze({ accounts: [getAccountMeta("ticket", accounts.ticket), getAccountMeta("tenant", accounts.tenant), getAccountMeta("player", accounts.player), getAccountMeta("permission", accounts.permission), getAccountMeta("permissionProgram", accounts.permissionProgram), getAccountMeta("systemProgram", accounts.systemProgram)], data: getSetupTicketPermissionInstructionDataEncoder().encode({}), programAddress } as SetupTicketPermissionInstruction<TProgramAddress, TAccountTicket, TAccountTenant, TAccountPlayer, TAccountPermission, TAccountPermissionProgram, TAccountSystemProgram>);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export type ParsedSetupTicketPermissionInstruction<TProgram extends string = typeof DUEL_PROGRAM_ADDRESS, TAccountMetas extends readonly AccountMeta[] = readonly AccountMeta[]> = { programAddress: Address<TProgram>;
|
|
94
|
+
accounts: {
|
|
95
|
+
ticket: TAccountMetas[0];
|
|
96
|
+
tenant: TAccountMetas[1];
|
|
97
|
+
player: TAccountMetas[2];
|
|
98
|
+
permission: TAccountMetas[3];
|
|
99
|
+
permissionProgram: TAccountMetas[4];
|
|
100
|
+
systemProgram: TAccountMetas[5];
|
|
101
|
+
};
|
|
102
|
+
data: SetupTicketPermissionInstructionData; };
|
|
103
|
+
|
|
104
|
+
export function parseSetupTicketPermissionInstruction<TProgram extends string, TAccountMetas extends readonly AccountMeta[]>(instruction: Instruction<TProgram> & InstructionWithAccounts<TAccountMetas> & InstructionWithData<ReadonlyUint8Array>): ParsedSetupTicketPermissionInstruction<TProgram, TAccountMetas> {
|
|
105
|
+
if (instruction.accounts.length < 6) {
|
|
106
|
+
throw new SolanaError(SOLANA_ERROR__PROGRAM_CLIENTS__INSUFFICIENT_ACCOUNT_METAS, { actualAccountMetas: instruction.accounts.length, expectedAccountMetas: 6 });
|
|
107
|
+
}
|
|
108
|
+
let accountIndex = 0;
|
|
109
|
+
const getNextAccount = () => {
|
|
110
|
+
const accountMeta = (instruction.accounts as TAccountMetas)[accountIndex]!;
|
|
111
|
+
accountIndex += 1;
|
|
112
|
+
return accountMeta;
|
|
113
|
+
}
|
|
114
|
+
return { programAddress: instruction.programAddress, accounts: { ticket: getNextAccount(), tenant: getNextAccount(), player: getNextAccount(), permission: getNextAccount(), permissionProgram: getNextAccount(), systemProgram: getNextAccount() }, data: getSetupTicketPermissionInstructionDataDecoder().decode(instruction.data) };
|
|
115
|
+
}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import { assertIsInstructionWithAccounts, containsBytes, fixEncoderSize, getBytesEncoder, SOLANA_ERROR__PROGRAM_CLIENTS__FAILED_TO_IDENTIFY_ACCOUNT, SOLANA_ERROR__PROGRAM_CLIENTS__FAILED_TO_IDENTIFY_INSTRUCTION, SOLANA_ERROR__PROGRAM_CLIENTS__UNRECOGNIZED_INSTRUCTION_TYPE, SolanaError, type Address, type ClientWithPayer, type ClientWithRpc, type ClientWithTransactionPlanning, type ClientWithTransactionSending, type GetAccountInfoApi, type GetMultipleAccountsApi, type Instruction, type InstructionWithData, type ReadonlyUint8Array } from '@solana/kit';
|
|
10
10
|
import { addSelfFetchFunctions, addSelfPlanAndSendFunctions, type SelfFetchFunctions, type SelfPlanAndSendFunctions } from '@solana/program-client-core';
|
|
11
11
|
import { getMatchTicketCodec, getQueueCodec, getTenantCodec, type MatchTicket, type MatchTicketArgs, type Queue, type QueueArgs, type Tenant, type TenantArgs } from '../accounts';
|
|
12
|
-
import { getCancelTicketInstructionAsync, getCloseTicketInstructionAsync, getCommitTicketsInstruction, getCreateTicketInstructionAsync, getDelegateQueueInstructionAsync, getDelegateTicketInstructionAsync, getFlushMatchesInstruction, getInitializeQueueInstructionAsync, getInitializeTenantInstructionAsync, getJoinQueueInstructionAsync, getProcessUndelegationInstruction, parseCancelTicketInstruction, parseCloseTicketInstruction, parseCommitTicketsInstruction, parseCreateTicketInstruction, parseDelegateQueueInstruction, parseDelegateTicketInstruction, parseFlushMatchesInstruction, parseInitializeQueueInstruction, parseInitializeTenantInstruction, parseJoinQueueInstruction, parseProcessUndelegationInstruction, type CancelTicketAsyncInput, type CloseTicketAsyncInput, type CommitTicketsInput, type CreateTicketAsyncInput, type DelegateQueueAsyncInput, type DelegateTicketAsyncInput, type FlushMatchesInput, type InitializeQueueAsyncInput, type InitializeTenantAsyncInput, type JoinQueueAsyncInput, type ParsedCancelTicketInstruction, type ParsedCloseTicketInstruction, type ParsedCommitTicketsInstruction, type ParsedCreateTicketInstruction, type ParsedDelegateQueueInstruction, type ParsedDelegateTicketInstruction, type ParsedFlushMatchesInstruction, type ParsedInitializeQueueInstruction, type ParsedInitializeTenantInstruction, type ParsedJoinQueueInstruction, type ParsedProcessUndelegationInstruction, type ProcessUndelegationInput } from '../instructions';
|
|
12
|
+
import { getCancelTicketInstructionAsync, getCloseTicketInstructionAsync, getCommitTicketsInstruction, getCreateTicketInstructionAsync, getDelegateQueueInstructionAsync, getDelegateTicketInstructionAsync, getFlushMatchesInstruction, getInitializeQueueInstructionAsync, getInitializeTenantInstructionAsync, getJoinQueueInstructionAsync, getProcessUndelegationInstruction, getSetupQueuePermissionInstructionAsync, getSetupTicketPermissionInstructionAsync, parseCancelTicketInstruction, parseCloseTicketInstruction, parseCommitTicketsInstruction, parseCreateTicketInstruction, parseDelegateQueueInstruction, parseDelegateTicketInstruction, parseFlushMatchesInstruction, parseInitializeQueueInstruction, parseInitializeTenantInstruction, parseJoinQueueInstruction, parseProcessUndelegationInstruction, parseSetupQueuePermissionInstruction, parseSetupTicketPermissionInstruction, type CancelTicketAsyncInput, type CloseTicketAsyncInput, type CommitTicketsInput, type CreateTicketAsyncInput, type DelegateQueueAsyncInput, type DelegateTicketAsyncInput, type FlushMatchesInput, type InitializeQueueAsyncInput, type InitializeTenantAsyncInput, type JoinQueueAsyncInput, type ParsedCancelTicketInstruction, type ParsedCloseTicketInstruction, type ParsedCommitTicketsInstruction, type ParsedCreateTicketInstruction, type ParsedDelegateQueueInstruction, type ParsedDelegateTicketInstruction, type ParsedFlushMatchesInstruction, type ParsedInitializeQueueInstruction, type ParsedInitializeTenantInstruction, type ParsedJoinQueueInstruction, type ParsedProcessUndelegationInstruction, type ParsedSetupQueuePermissionInstruction, type ParsedSetupTicketPermissionInstruction, type ProcessUndelegationInput, type SetupQueuePermissionAsyncInput, type SetupTicketPermissionAsyncInput } from '../instructions';
|
|
13
13
|
|
|
14
14
|
export const DUEL_PROGRAM_ADDRESS = 'EdZzUwKd1X2ZWjxLPpz1cpEzMF7RUZC43Pq64v1VcK5X' as Address<'EdZzUwKd1X2ZWjxLPpz1cpEzMF7RUZC43Pq64v1VcK5X'>;
|
|
15
15
|
|
|
@@ -23,7 +23,7 @@ if (containsBytes(data, fixEncoderSize(getBytesEncoder(), 8).encode(new Uint8Arr
|
|
|
23
23
|
throw new SolanaError(SOLANA_ERROR__PROGRAM_CLIENTS__FAILED_TO_IDENTIFY_ACCOUNT, { accountData: data, programName: "duel" });
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
export enum DuelInstruction { CancelTicket, CloseTicket, CommitTickets, CreateTicket, DelegateQueue, DelegateTicket, FlushMatches, InitializeQueue, InitializeTenant, JoinQueue, ProcessUndelegation }
|
|
26
|
+
export enum DuelInstruction { CancelTicket, CloseTicket, CommitTickets, CreateTicket, DelegateQueue, DelegateTicket, FlushMatches, InitializeQueue, InitializeTenant, JoinQueue, ProcessUndelegation, SetupQueuePermission, SetupTicketPermission }
|
|
27
27
|
|
|
28
28
|
export function identifyDuelInstruction(instruction: { data: ReadonlyUint8Array } | ReadonlyUint8Array): DuelInstruction {
|
|
29
29
|
const data = 'data' in instruction ? instruction.data : instruction;
|
|
@@ -38,6 +38,8 @@ if (containsBytes(data, fixEncoderSize(getBytesEncoder(), 8).encode(new Uint8Arr
|
|
|
38
38
|
if (containsBytes(data, fixEncoderSize(getBytesEncoder(), 8).encode(new Uint8Array([94, 120, 34, 186, 57, 167, 241, 206])), 0)) { return DuelInstruction.InitializeTenant; }
|
|
39
39
|
if (containsBytes(data, fixEncoderSize(getBytesEncoder(), 8).encode(new Uint8Array([157, 115, 48, 109, 65, 86, 203, 238])), 0)) { return DuelInstruction.JoinQueue; }
|
|
40
40
|
if (containsBytes(data, fixEncoderSize(getBytesEncoder(), 8).encode(new Uint8Array([196, 28, 41, 206, 48, 37, 51, 167])), 0)) { return DuelInstruction.ProcessUndelegation; }
|
|
41
|
+
if (containsBytes(data, fixEncoderSize(getBytesEncoder(), 8).encode(new Uint8Array([223, 132, 77, 15, 224, 155, 125, 224])), 0)) { return DuelInstruction.SetupQueuePermission; }
|
|
42
|
+
if (containsBytes(data, fixEncoderSize(getBytesEncoder(), 8).encode(new Uint8Array([164, 29, 7, 235, 183, 223, 11, 85])), 0)) { return DuelInstruction.SetupTicketPermission; }
|
|
41
43
|
throw new SolanaError(SOLANA_ERROR__PROGRAM_CLIENTS__FAILED_TO_IDENTIFY_INSTRUCTION, { instructionData: data, programName: "duel" });
|
|
42
44
|
}
|
|
43
45
|
|
|
@@ -53,6 +55,8 @@ export type ParsedDuelInstruction<TProgram extends string = 'EdZzUwKd1X2ZWjxLPpz
|
|
|
53
55
|
| { instructionType: DuelInstruction.InitializeTenant } & ParsedInitializeTenantInstruction<TProgram>
|
|
54
56
|
| { instructionType: DuelInstruction.JoinQueue } & ParsedJoinQueueInstruction<TProgram>
|
|
55
57
|
| { instructionType: DuelInstruction.ProcessUndelegation } & ParsedProcessUndelegationInstruction<TProgram>
|
|
58
|
+
| { instructionType: DuelInstruction.SetupQueuePermission } & ParsedSetupQueuePermissionInstruction<TProgram>
|
|
59
|
+
| { instructionType: DuelInstruction.SetupTicketPermission } & ParsedSetupTicketPermissionInstruction<TProgram>
|
|
56
60
|
|
|
57
61
|
|
|
58
62
|
export function parseDuelInstruction<TProgram extends string>(
|
|
@@ -83,6 +87,10 @@ case DuelInstruction.JoinQueue: { assertIsInstructionWithAccounts(instruction);
|
|
|
83
87
|
return { instructionType: DuelInstruction.JoinQueue, ...parseJoinQueueInstruction(instruction) }; }
|
|
84
88
|
case DuelInstruction.ProcessUndelegation: { assertIsInstructionWithAccounts(instruction);
|
|
85
89
|
return { instructionType: DuelInstruction.ProcessUndelegation, ...parseProcessUndelegationInstruction(instruction) }; }
|
|
90
|
+
case DuelInstruction.SetupQueuePermission: { assertIsInstructionWithAccounts(instruction);
|
|
91
|
+
return { instructionType: DuelInstruction.SetupQueuePermission, ...parseSetupQueuePermissionInstruction(instruction) }; }
|
|
92
|
+
case DuelInstruction.SetupTicketPermission: { assertIsInstructionWithAccounts(instruction);
|
|
93
|
+
return { instructionType: DuelInstruction.SetupTicketPermission, ...parseSetupTicketPermissionInstruction(instruction) }; }
|
|
86
94
|
default: throw new SolanaError(SOLANA_ERROR__PROGRAM_CLIENTS__UNRECOGNIZED_INSTRUCTION_TYPE, { instructionType: instructionType as string, programName: "duel" });
|
|
87
95
|
}
|
|
88
96
|
}
|
|
@@ -91,13 +99,13 @@ export type DuelPlugin = { accounts: DuelPluginAccounts; instructions: DuelPlugi
|
|
|
91
99
|
|
|
92
100
|
export type DuelPluginAccounts = { matchTicket: ReturnType<typeof getMatchTicketCodec> & SelfFetchFunctions<MatchTicketArgs, MatchTicket>; queue: ReturnType<typeof getQueueCodec> & SelfFetchFunctions<QueueArgs, Queue>; tenant: ReturnType<typeof getTenantCodec> & SelfFetchFunctions<TenantArgs, Tenant>; }
|
|
93
101
|
|
|
94
|
-
export type DuelPluginInstructions = { cancelTicket: (input: CancelTicketAsyncInput) => ReturnType<typeof getCancelTicketInstructionAsync> & SelfPlanAndSendFunctions; closeTicket: (input: CloseTicketAsyncInput) => ReturnType<typeof getCloseTicketInstructionAsync> & SelfPlanAndSendFunctions; commitTickets: (input: MakeOptional<CommitTicketsInput, "payer">) => ReturnType<typeof getCommitTicketsInstruction> & SelfPlanAndSendFunctions; createTicket: (input: CreateTicketAsyncInput) => ReturnType<typeof getCreateTicketInstructionAsync> & SelfPlanAndSendFunctions; delegateQueue: (input: MakeOptional<DelegateQueueAsyncInput, "payer">) => ReturnType<typeof getDelegateQueueInstructionAsync> & SelfPlanAndSendFunctions; delegateTicket: (input: MakeOptional<DelegateTicketAsyncInput, "payer">) => ReturnType<typeof getDelegateTicketInstructionAsync> & SelfPlanAndSendFunctions; flushMatches: (input: FlushMatchesInput) => ReturnType<typeof getFlushMatchesInstruction> & SelfPlanAndSendFunctions; initializeQueue: (input: InitializeQueueAsyncInput) => ReturnType<typeof getInitializeQueueInstructionAsync> & SelfPlanAndSendFunctions; initializeTenant: (input: InitializeTenantAsyncInput) => ReturnType<typeof getInitializeTenantInstructionAsync> & SelfPlanAndSendFunctions; joinQueue: (input: JoinQueueAsyncInput) => ReturnType<typeof getJoinQueueInstructionAsync> & SelfPlanAndSendFunctions; processUndelegation: (input: MakeOptional<ProcessUndelegationInput, "payer">) => ReturnType<typeof getProcessUndelegationInstruction> & SelfPlanAndSendFunctions; }
|
|
102
|
+
export type DuelPluginInstructions = { cancelTicket: (input: CancelTicketAsyncInput) => ReturnType<typeof getCancelTicketInstructionAsync> & SelfPlanAndSendFunctions; closeTicket: (input: CloseTicketAsyncInput) => ReturnType<typeof getCloseTicketInstructionAsync> & SelfPlanAndSendFunctions; commitTickets: (input: MakeOptional<CommitTicketsInput, "payer">) => ReturnType<typeof getCommitTicketsInstruction> & SelfPlanAndSendFunctions; createTicket: (input: CreateTicketAsyncInput) => ReturnType<typeof getCreateTicketInstructionAsync> & SelfPlanAndSendFunctions; delegateQueue: (input: MakeOptional<DelegateQueueAsyncInput, "payer">) => ReturnType<typeof getDelegateQueueInstructionAsync> & SelfPlanAndSendFunctions; delegateTicket: (input: MakeOptional<DelegateTicketAsyncInput, "payer">) => ReturnType<typeof getDelegateTicketInstructionAsync> & SelfPlanAndSendFunctions; flushMatches: (input: FlushMatchesInput) => ReturnType<typeof getFlushMatchesInstruction> & SelfPlanAndSendFunctions; initializeQueue: (input: InitializeQueueAsyncInput) => ReturnType<typeof getInitializeQueueInstructionAsync> & SelfPlanAndSendFunctions; initializeTenant: (input: InitializeTenantAsyncInput) => ReturnType<typeof getInitializeTenantInstructionAsync> & SelfPlanAndSendFunctions; joinQueue: (input: JoinQueueAsyncInput) => ReturnType<typeof getJoinQueueInstructionAsync> & SelfPlanAndSendFunctions; processUndelegation: (input: MakeOptional<ProcessUndelegationInput, "payer">) => ReturnType<typeof getProcessUndelegationInstruction> & SelfPlanAndSendFunctions; setupQueuePermission: (input: SetupQueuePermissionAsyncInput) => ReturnType<typeof getSetupQueuePermissionInstructionAsync> & SelfPlanAndSendFunctions; setupTicketPermission: (input: SetupTicketPermissionAsyncInput) => ReturnType<typeof getSetupTicketPermissionInstructionAsync> & SelfPlanAndSendFunctions; }
|
|
95
103
|
|
|
96
104
|
export type DuelPluginRequirements = ClientWithRpc<GetAccountInfoApi & GetMultipleAccountsApi> & ClientWithPayer & ClientWithTransactionPlanning & ClientWithTransactionSending
|
|
97
105
|
|
|
98
106
|
export function duelProgram() {
|
|
99
107
|
return <T extends DuelPluginRequirements>(client: T) => {
|
|
100
|
-
return { ...client, duel: <DuelPlugin>{ accounts: { matchTicket: addSelfFetchFunctions(client, getMatchTicketCodec()), queue: addSelfFetchFunctions(client, getQueueCodec()), tenant: addSelfFetchFunctions(client, getTenantCodec()) }, instructions: { cancelTicket: input => addSelfPlanAndSendFunctions(client, getCancelTicketInstructionAsync(input)), closeTicket: input => addSelfPlanAndSendFunctions(client, getCloseTicketInstructionAsync(input)), commitTickets: input => addSelfPlanAndSendFunctions(client, getCommitTicketsInstruction({ ...input, payer: input.payer ?? client.payer })), createTicket: input => addSelfPlanAndSendFunctions(client, getCreateTicketInstructionAsync(input)), delegateQueue: input => addSelfPlanAndSendFunctions(client, getDelegateQueueInstructionAsync({ ...input, payer: input.payer ?? client.payer })), delegateTicket: input => addSelfPlanAndSendFunctions(client, getDelegateTicketInstructionAsync({ ...input, payer: input.payer ?? client.payer })), flushMatches: input => addSelfPlanAndSendFunctions(client, getFlushMatchesInstruction(input)), initializeQueue: input => addSelfPlanAndSendFunctions(client, getInitializeQueueInstructionAsync(input)), initializeTenant: input => addSelfPlanAndSendFunctions(client, getInitializeTenantInstructionAsync(input)), joinQueue: input => addSelfPlanAndSendFunctions(client, getJoinQueueInstructionAsync(input)), processUndelegation: input => addSelfPlanAndSendFunctions(client, getProcessUndelegationInstruction({ ...input, payer: input.payer ?? client.payer.address })) } } };
|
|
108
|
+
return { ...client, duel: <DuelPlugin>{ accounts: { matchTicket: addSelfFetchFunctions(client, getMatchTicketCodec()), queue: addSelfFetchFunctions(client, getQueueCodec()), tenant: addSelfFetchFunctions(client, getTenantCodec()) }, instructions: { cancelTicket: input => addSelfPlanAndSendFunctions(client, getCancelTicketInstructionAsync(input)), closeTicket: input => addSelfPlanAndSendFunctions(client, getCloseTicketInstructionAsync(input)), commitTickets: input => addSelfPlanAndSendFunctions(client, getCommitTicketsInstruction({ ...input, payer: input.payer ?? client.payer })), createTicket: input => addSelfPlanAndSendFunctions(client, getCreateTicketInstructionAsync(input)), delegateQueue: input => addSelfPlanAndSendFunctions(client, getDelegateQueueInstructionAsync({ ...input, payer: input.payer ?? client.payer })), delegateTicket: input => addSelfPlanAndSendFunctions(client, getDelegateTicketInstructionAsync({ ...input, payer: input.payer ?? client.payer })), flushMatches: input => addSelfPlanAndSendFunctions(client, getFlushMatchesInstruction(input)), initializeQueue: input => addSelfPlanAndSendFunctions(client, getInitializeQueueInstructionAsync(input)), initializeTenant: input => addSelfPlanAndSendFunctions(client, getInitializeTenantInstructionAsync(input)), joinQueue: input => addSelfPlanAndSendFunctions(client, getJoinQueueInstructionAsync(input)), processUndelegation: input => addSelfPlanAndSendFunctions(client, getProcessUndelegationInstruction({ ...input, payer: input.payer ?? client.payer.address })), setupQueuePermission: input => addSelfPlanAndSendFunctions(client, getSetupQueuePermissionInstructionAsync(input)), setupTicketPermission: input => addSelfPlanAndSendFunctions(client, getSetupTicketPermissionInstructionAsync(input)) } } };
|
|
101
109
|
};
|
|
102
110
|
}
|
|
103
111
|
|
package/src/player.ts
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createSolanaRpc,
|
|
3
|
+
AccountRole,
|
|
3
4
|
type Address,
|
|
4
5
|
type TransactionSigner,
|
|
5
6
|
type Rpc,
|
|
6
7
|
type SolanaRpcApi,
|
|
8
|
+
type Instruction,
|
|
7
9
|
} from "@solana/kit";
|
|
8
10
|
import {
|
|
9
11
|
getCreateTicketInstructionAsync,
|
|
10
12
|
getDelegateTicketInstructionAsync,
|
|
13
|
+
getSetupTicketPermissionInstructionAsync,
|
|
11
14
|
getJoinQueueInstructionAsync,
|
|
12
15
|
getCancelTicketInstructionAsync,
|
|
13
16
|
getCloseTicketInstructionAsync,
|
|
@@ -69,6 +72,7 @@ export class MatchmakingPlayer {
|
|
|
69
72
|
queue: Address,
|
|
70
73
|
tenant: Address,
|
|
71
74
|
playerData: Address,
|
|
75
|
+
callbackProgram?: Address,
|
|
72
76
|
): Promise<string> {
|
|
73
77
|
const ix = await getJoinQueueInstructionAsync({
|
|
74
78
|
queue,
|
|
@@ -76,7 +80,11 @@ export class MatchmakingPlayer {
|
|
|
76
80
|
playerData,
|
|
77
81
|
signer: this.signer,
|
|
78
82
|
}, { programAddress: this.programId });
|
|
79
|
-
|
|
83
|
+
const ixFinal = callbackProgram
|
|
84
|
+
? { ...ix, accounts: [...ix.accounts, { address: callbackProgram, role: 0 as const }] }
|
|
85
|
+
: ix;
|
|
86
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
87
|
+
return sendInstruction(this.rpc, ixFinal as any, this.signer);
|
|
80
88
|
}
|
|
81
89
|
|
|
82
90
|
async cancelTicket(tenant: Address): Promise<string> {
|
|
@@ -122,6 +130,69 @@ export class MatchmakingPlayer {
|
|
|
122
130
|
return null;
|
|
123
131
|
}
|
|
124
132
|
|
|
133
|
+
/**
|
|
134
|
+
* High-level: full matchmaking TEE entry flow.
|
|
135
|
+
* Creates ticket on L1, sets up permission PDA (so only player + queue authority can read it),
|
|
136
|
+
* delegates the permission PDA and ticket to TEE, then joins the queue.
|
|
137
|
+
* Use individual methods (createTicket, delegateTicket, joinQueue) as escape hatches if needed.
|
|
138
|
+
*/
|
|
139
|
+
async enterQueue(
|
|
140
|
+
tenant: Address,
|
|
141
|
+
queue: Address,
|
|
142
|
+
playerData: Address,
|
|
143
|
+
teeRpc: Rpc<SolanaRpcApi>,
|
|
144
|
+
teeUrlWithToken: string,
|
|
145
|
+
validator?: Address,
|
|
146
|
+
callbackProgram?: Address,
|
|
147
|
+
): Promise<Address> {
|
|
148
|
+
const player = this.signer.address as Address;
|
|
149
|
+
const ticketPda = await this.getTicketPda(player, tenant);
|
|
150
|
+
|
|
151
|
+
// 1. Create ticket on L1
|
|
152
|
+
await this.createTicket(tenant);
|
|
153
|
+
|
|
154
|
+
// 2. Create Permission PDA for the ticket (CPI from duel program with invoke_signed)
|
|
155
|
+
const permissionPda = await utils.derivePermissionPda(ticketPda);
|
|
156
|
+
const setupIx = await getSetupTicketPermissionInstructionAsync({
|
|
157
|
+
player: this.signer,
|
|
158
|
+
tenant,
|
|
159
|
+
permission: permissionPda,
|
|
160
|
+
permissionProgram: utils.PERMISSION_PROGRAM,
|
|
161
|
+
}, { programAddress: this.programId });
|
|
162
|
+
await sendInstruction(this.rpc, setupIx, this.signer);
|
|
163
|
+
|
|
164
|
+
// 3. Delegate Permission PDA to TEE (called on permission program, player signs)
|
|
165
|
+
const { delegationBuffer, delegationRecord, delegationMetadata } =
|
|
166
|
+
await utils.derivePermissionDelegationPdas(permissionPda);
|
|
167
|
+
const delegatePermIx: Instruction = {
|
|
168
|
+
programAddress: utils.PERMISSION_PROGRAM,
|
|
169
|
+
data: new Uint8Array([3, 0, 0, 0, 0, 0, 0, 0]),
|
|
170
|
+
accounts: [
|
|
171
|
+
{ address: this.signer.address, role: AccountRole.WRITABLE_SIGNER },
|
|
172
|
+
{ address: this.signer.address, role: AccountRole.READONLY_SIGNER },
|
|
173
|
+
{ address: ticketPda, role: AccountRole.READONLY },
|
|
174
|
+
{ address: permissionPda, role: AccountRole.WRITABLE },
|
|
175
|
+
{ address: "11111111111111111111111111111111" as Address, role: AccountRole.READONLY },
|
|
176
|
+
{ address: utils.PERMISSION_PROGRAM, role: AccountRole.READONLY },
|
|
177
|
+
{ address: delegationBuffer, role: AccountRole.WRITABLE },
|
|
178
|
+
{ address: delegationRecord, role: AccountRole.WRITABLE },
|
|
179
|
+
{ address: delegationMetadata, role: AccountRole.WRITABLE },
|
|
180
|
+
{ address: utils.DELEGATION_PROGRAM, role: AccountRole.READONLY },
|
|
181
|
+
...(validator ? [{ address: validator, role: AccountRole.READONLY }] : []),
|
|
182
|
+
],
|
|
183
|
+
};
|
|
184
|
+
await sendInstruction(this.rpc, delegatePermIx, this.signer);
|
|
185
|
+
|
|
186
|
+
// 4. Delegate ticket to TEE
|
|
187
|
+
await this.delegateTicket(player, tenant, validator);
|
|
188
|
+
|
|
189
|
+
// 5. Join the queue on TEE
|
|
190
|
+
const teeClient = new MatchmakingPlayer(teeRpc, this.signer, this.programId);
|
|
191
|
+
await teeClient.joinQueue(queue, tenant, playerData, callbackProgram);
|
|
192
|
+
|
|
193
|
+
return ticketPda;
|
|
194
|
+
}
|
|
195
|
+
|
|
125
196
|
/** Create a new MatchmakingPlayer pointing at a TEE RPC endpoint. */
|
|
126
197
|
withRpc(teeUrl: string): MatchmakingPlayer {
|
|
127
198
|
return new MatchmakingPlayer(createSolanaRpc(teeUrl), this.signer, this.programId);
|
package/src/tee.ts
CHANGED
|
@@ -45,35 +45,31 @@ export async function getAuthToken(
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
/**
|
|
48
|
-
* Poll the TEE
|
|
49
|
-
*
|
|
48
|
+
* Poll the TEE until the Permission PDA for the given account is active (authorizedUsers non-empty).
|
|
49
|
+
* This confirms the TEE has picked up the delegated Permission PDA and is enforcing access control.
|
|
50
|
+
* Returns true if active before timeout, false otherwise.
|
|
50
51
|
*/
|
|
51
|
-
export async function
|
|
52
|
+
export async function waitForPermission(
|
|
52
53
|
teeUrlWithToken: string,
|
|
53
|
-
|
|
54
|
-
timeoutMs =
|
|
54
|
+
accountAddress: Address,
|
|
55
|
+
timeoutMs = 10000,
|
|
55
56
|
): Promise<boolean> {
|
|
56
|
-
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
permissionUrl = `${baseUrl}/permission?${tokenParam}&pubkey=${pda}`;
|
|
61
|
-
} else {
|
|
62
|
-
permissionUrl = `${baseUrl}/permission?pubkey=${pda}`;
|
|
63
|
-
}
|
|
57
|
+
const [baseUrl, token] = teeUrlWithToken.replace("/?", "?").split("?");
|
|
58
|
+
const permUrl = token
|
|
59
|
+
? `${baseUrl}/permission?${token}&pubkey=${accountAddress}`
|
|
60
|
+
: `${baseUrl}/permission?pubkey=${accountAddress}`;
|
|
64
61
|
|
|
65
|
-
const
|
|
66
|
-
while (Date.now()
|
|
62
|
+
const deadline = Date.now() + timeoutMs;
|
|
63
|
+
while (Date.now() < deadline) {
|
|
67
64
|
try {
|
|
68
|
-
const res = await fetch(
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
if (authorizedUsers && authorizedUsers.length > 0) return true;
|
|
72
|
-
}
|
|
65
|
+
const res = await fetch(permUrl);
|
|
66
|
+
const json = (await res.json()) as { authorizedUsers?: unknown[] | null };
|
|
67
|
+
if (json.authorizedUsers && json.authorizedUsers.length > 0) return true;
|
|
73
68
|
} catch {
|
|
74
|
-
// ignore transient errors
|
|
69
|
+
// ignore transient errors
|
|
75
70
|
}
|
|
76
|
-
await new Promise((r) => setTimeout(r,
|
|
71
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
77
72
|
}
|
|
78
73
|
return false;
|
|
79
74
|
}
|
|
75
|
+
|