diff --git a/ddl/migrations/0177_sol_locker_vesting_escrows.sql b/ddl/migrations/0177_sol_locker_vesting_escrows.sql new file mode 100644 index 00000000..11369cb6 --- /dev/null +++ b/ddl/migrations/0177_sol_locker_vesting_escrows.sql @@ -0,0 +1,26 @@ +BEGIN; + +CREATE TABLE IF NOT EXISTS sol_locker_vesting_escrows ( + account TEXT PRIMARY KEY, + slot BIGINT NOT NULL, + recipient TEXT NOT NULL, + token_mint TEXT NOT NULL, + creator TEXT NOT NULL, + base TEXT NOT NULL, + escrow_bump SMALLINT NOT NULL, + update_recipient_mode SMALLINT NOT NULL, + cancel_mode SMALLINT NOT NULL, + token_program_flag SMALLINT NOT NULL, + cliff_time BIGINT NOT NULL, + frequency BIGINT NOT NULL, + cliff_unlock_amount BIGINT NOT NULL, + amount_per_period BIGINT NOT NULL, + number_of_period BIGINT NOT NULL, + total_claimed_amount BIGINT NOT NULL, + vesting_start_time BIGINT NOT NULL, + cancelled_at BIGINT NOT NULL, + created_at TIMESTAMP DEFAULT NOW(), + updated_at TIMESTAMP DEFAULT NOW() +); + +COMMIT; \ No newline at end of file diff --git a/solana/indexer/dbc/indexer.go b/solana/indexer/dbc/indexer.go index aa26eb18..bcae20ba 100644 --- a/solana/indexer/dbc/indexer.go +++ b/solana/indexer/dbc/indexer.go @@ -12,6 +12,7 @@ import ( "api.audius.co/database" "api.audius.co/solana/indexer/common" "api.audius.co/solana/spl/programs/meteora_dbc" + "api.audius.co/solana/spl/programs/meteora_locker" bin "github.com/gagliardetto/binary" "github.com/gagliardetto/solana-go" "github.com/gagliardetto/solana-go/rpc" @@ -229,6 +230,25 @@ func (d *Indexer) HandleUpdate(ctx context.Context, msg *pb.SubscribeUpdate) err err = d.processTransaction(ctx, txRes.Slot, tx) } } + + // Handle Vesting Escrow updates + if len(accountUpdate.Account.Data) > 8 && bytes.Equal(accountUpdate.Account.Data[:8], meteora_locker.Account_VestingEscrow[:]) { + var escrow meteora_locker.VestingEscrow + err := bin.NewBorshDecoder(accountUpdate.Account.Data).Decode(&escrow) + if err != nil { + return fmt.Errorf("failed to decode Vesting Escrow account: %w", err) + } + account := solana.PublicKeyFromBytes(accountUpdate.Account.Pubkey) + + err = processVestingEscrowUpdate(ctx, d.pool, accountUpdate.Slot, account, &escrow) + if err != nil { + return fmt.Errorf("failed to process Vesting Escrow update: %w", err) + } + d.logger.Debug("processed Vesting Escrow update", + zap.String("account", account.String()), + zap.String("recipient", escrow.Recipient.String()), + ) + } } return nil } @@ -320,6 +340,34 @@ func (d *Indexer) makeSubscriptionRequest(ctx context.Context, mints []string) * }, } subscription.Accounts[mint] = &poolFilter + + lockFilter := pb.SubscribeRequestFilterAccounts{ + Owner: []string{meteora_locker.ProgramID.String()}, + Filters: []*pb.SubscribeRequestFilterAccountsFilter{ + { + Filter: &pb.SubscribeRequestFilterAccountsFilter_Memcmp{ + Memcmp: &pb.SubscribeRequestFilterAccountsFilterMemcmp{ + Offset: 0, + Data: &pb.SubscribeRequestFilterAccountsFilterMemcmp_Bytes{ + Bytes: meteora_locker.Account_VestingEscrow[:], + }, + }, + }, + }, + { + Filter: &pb.SubscribeRequestFilterAccountsFilter_Memcmp{ + Memcmp: &pb.SubscribeRequestFilterAccountsFilterMemcmp{ + // Pool mint is after discriminator and recipient + Offset: 8 + 32, + Data: &pb.SubscribeRequestFilterAccountsFilterMemcmp_Base58{ + Base58: mint, + }, + }, + }, + }, + }, + } + subscription.Accounts["lock_"+mint] = &lockFilter } configFilter := pb.SubscribeRequestFilterAccounts{ @@ -430,6 +478,30 @@ func processDbcConfigUpdate( return nil } +func processVestingEscrowUpdate( + ctx context.Context, + db database.DbPool, + slot uint64, + account solana.PublicKey, + escrow *meteora_locker.VestingEscrow, +) error { + sqlTx, err := db.Begin(ctx) + if err != nil { + return fmt.Errorf("failed to begin transaction: %w", err) + } + defer sqlTx.Rollback(ctx) + + err = upsertVestingEscrow(ctx, sqlTx, slot, account, escrow) + if err != nil { + return fmt.Errorf("failed to upsert vesting escrow: %w", err) + } + err = sqlTx.Commit(ctx) + if err != nil { + return fmt.Errorf("failed to commit transaction: %w", err) + } + return nil +} + func (i *Indexer) processTransaction(ctx context.Context, slot uint64, tx *solana.Transaction) error { signature := tx.Signatures[0].String() logger := i.logger.With( diff --git a/solana/indexer/dbc/indexer_test.go b/solana/indexer/dbc/indexer_test.go index 95c84ca8..9ec0de97 100644 --- a/solana/indexer/dbc/indexer_test.go +++ b/solana/indexer/dbc/indexer_test.go @@ -403,3 +403,82 @@ func TestHandleUpdate_Config(t *testing.T) { require.NoError(t, err, "failed to query for dbc config vestings") assert.True(t, exists, "dbc config vestings should exist after indexing") } + +func TestHandleUpdate_VestingEscrow(t *testing.T) { + pool := database.CreateTestDatabase(t, "test_solana_indexer_dbc") + rpcClient := fake_rpc_client.FakeRpcClient{} + logger := zap.NewNop() + + indexer := New(common.GrpcConfig{}, &rpcClient, pool, config.Cfg, nil, logger) + + escrowAddress := solana.MustPublicKeyFromBase58("7fXoYtLh1bG7q3Yh3b3Y9T5oX5nU5Y1Z6L8v1K5vU6Lm") + escrowBase64 := "9He3BEl0h8Pma7+K8q1+Y5zeZOJijiDxit+NwzCo6fSDuaAK1rtuUHcaLxqg1AjgXzqUrEhTyula0B3153h+c/pj9a/R+ETB2mNoH3KGvMgGcZ4sK1CiAVckO/yWaLEVILxThD7c2wiAwc02YNTKuGhqgHA0AyospRPz5Pq9NNsMGdSqUKuLgf4CAQAAAAAAwZvyaAAAAACAUQEAAAAAAAAAAAAAAAAADhyqNy35AAAhBwAAAAAAAAYAAAAAAAAAwZvyaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" + escrowData, err := base64.StdEncoding.DecodeString(escrowBase64) + require.NoError(t, err) + + update := pb.SubscribeUpdate{ + UpdateOneof: &pb.SubscribeUpdate_Account{ + Account: &pb.SubscribeUpdateAccount{ + Slot: 600000000, + Account: &pb.SubscribeUpdateAccountInfo{ + Pubkey: escrowAddress.Bytes(), + Data: escrowData, + TxnSignature: nil, + }, + }, + }, + } + + err = indexer.HandleUpdate(t.Context(), &update) + require.NoError(t, err) + + // Verify that the vesting escrow was inserted + sql := ` + SELECT EXISTS ( + SELECT 1 + FROM sol_locker_vesting_escrows + WHERE account = @account + AND slot = @slot + AND recipient = @recipient + AND token_mint = @token_mint + AND creator = @creator + AND base = @base + AND escrow_bump = @escrow_bump + AND update_recipient_mode = @update_recipient_mode + AND cancel_mode = @cancel_mode + AND token_program_flag = @token_program_flag + AND cliff_time = @cliff_time + AND frequency = @frequency + AND cliff_unlock_amount = @cliff_unlock_amount + AND amount_per_period = @amount_per_period + AND number_of_period = @number_of_period + AND total_claimed_amount = @total_claimed_amount + AND vesting_start_time = @vesting_start_time + AND cancelled_at = @cancelled_at + LIMIT 1 + ) + ` + var exists bool + err = pool.QueryRow(t.Context(), sql, pgx.NamedArgs{ + "account": escrowAddress.String(), + "slot": int64(600000000), + "recipient": "GWU4gnhaGPdhh4mcXudMpBXRUVJxqRPPXaSc8UkU2D3u", + "token_mint": "91vg3y8HsmcShJARjpEMZBu5z2W5BwY4fdCj46QZCCnk", + "creator": "FhVo3mqL8PW5pH5U2CN4XE33DokiyZnUwuGpH2hmHLuM", + "base": "9fcau4PNu4JGuS5J8dqP2qJiQbzxu5KeV12a94khdTma", + "escrow_bump": uint8(254), + "update_recipient_mode": int8(2), + "cancel_mode": int8(1), + "token_program_flag": int8(0), + "cliff_time": int64(1760730049), + "frequency": int64(86400), + "cliff_unlock_amount": uint64(0), + "amount_per_period": uint64(273972602739726), + "number_of_period": uint64(1825), + "total_claimed_amount": uint64(6), + "vesting_start_time": int64(1760730049), + "cancelled_at": int64(0), + }).Scan(&exists) + require.NoError(t, err, "failed to query for vesting escrow") + assert.True(t, exists, "vesting escrow should exist after indexing") +} diff --git a/solana/indexer/dbc/locker.go b/solana/indexer/dbc/locker.go new file mode 100644 index 00000000..566ea721 --- /dev/null +++ b/solana/indexer/dbc/locker.go @@ -0,0 +1,105 @@ +package dbc + +import ( + "context" + + "api.audius.co/database" + "api.audius.co/solana/spl/programs/meteora_locker" + "github.com/gagliardetto/solana-go" + "github.com/jackc/pgx/v5" +) + +func upsertVestingEscrow( + ctx context.Context, + db database.DBTX, + slot uint64, + account solana.PublicKey, + escrow *meteora_locker.VestingEscrow, +) error { + sql := ` + INSERT INTO sol_locker_vesting_escrows ( + account, + slot, + recipient, + token_mint, + creator, + base, + escrow_bump, + update_recipient_mode, + cancel_mode, + token_program_flag, + cliff_time, + frequency, + cliff_unlock_amount, + amount_per_period, + number_of_period, + total_claimed_amount, + vesting_start_time, + cancelled_at, + created_at, + updated_at + ) VALUES ( + @account, + @slot, + @recipient, + @tokenMint, + @creator, + @base, + @escrowBump, + @updateRecipientMode, + @cancelMode, + @tokenProgramFlag, + @cliffTime, + @frequency, + @cliffUnlockAmount, + @amountPerPeriod, + @numberOfPeriod, + @totalClaimedAmount, + @vestingStartTime, + @cancelledAt, + NOW(), + NOW() + ) + ON CONFLICT (account) DO UPDATE SET + slot = EXCLUDED.slot, + recipient = EXCLUDED.recipient, + token_mint = EXCLUDED.token_mint, + creator = EXCLUDED.creator, + base = EXCLUDED.base, + escrow_bump = EXCLUDED.escrow_bump, + update_recipient_mode = EXCLUDED.update_recipient_mode, + cancel_mode = EXCLUDED.cancel_mode, + token_program_flag = EXCLUDED.token_program_flag, + cliff_time = EXCLUDED.cliff_time, + frequency = EXCLUDED.frequency, + cliff_unlock_amount = EXCLUDED.cliff_unlock_amount, + amount_per_period = EXCLUDED.amount_per_period, + number_of_period = EXCLUDED.number_of_period, + total_claimed_amount = EXCLUDED.total_claimed_amount, + vesting_start_time = EXCLUDED.vesting_start_time, + cancelled_at = EXCLUDED.cancelled_at, + updated_at = NOW() + WHERE sol_locker_vesting_escrows.slot > EXCLUDED.slot + ;` + _, err := db.Exec(ctx, sql, pgx.NamedArgs{ + "account": account.String(), + "slot": slot, + "recipient": escrow.Recipient.String(), + "tokenMint": escrow.TokenMint.String(), + "creator": escrow.Creator.String(), + "base": escrow.Base.String(), + "escrowBump": escrow.EscrowBump, + "updateRecipientMode": int8(escrow.UpdateRecipientMode), + "cancelMode": int8(escrow.CancelMode), + "tokenProgramFlag": int8(escrow.TokenProgramFlag), + "cliffTime": escrow.CliffTime, + "frequency": escrow.Frequency, + "cliffUnlockAmount": escrow.CliffUnlockAmount, + "amountPerPeriod": escrow.AmountPerPeriod, + "numberOfPeriod": escrow.NumberOfPeriod, + "totalClaimedAmount": escrow.TotalClaimedAmount, + "vestingStartTime": escrow.VestingStartTime, + "cancelledAt": escrow.CancelledAt, + }) + return err +} diff --git a/solana/spl/programs/meteora_locker/discriminators.go b/solana/spl/programs/meteora_locker/discriminators.go new file mode 100644 index 00000000..195f54e9 --- /dev/null +++ b/solana/spl/programs/meteora_locker/discriminators.go @@ -0,0 +1,40 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. +// This file contains the discriminators for accounts and events defined in the IDL. + +package meteora_locker + +// Account discriminators +var ( + Account_RootEscrow = [8]byte{253, 209, 220, 107, 206, 191, 71, 158} + Account_VestingEscrow = [8]byte{244, 119, 183, 4, 73, 116, 135, 195} + Account_VestingEscrowMetadata = [8]byte{24, 204, 166, 104, 87, 158, 76, 13} +) + +// Event discriminators +var ( + Event_EventCancelVestingEscrow = [8]byte{113, 2, 117, 173, 195, 39, 101, 155} + Event_EventCancelVestingEscrowV3 = [8]byte{41, 143, 236, 79, 116, 120, 91, 143} + Event_EventClaim = [8]byte{171, 144, 1, 189, 120, 200, 38, 11} + Event_EventClaimV3 = [8]byte{229, 197, 142, 10, 41, 122, 171, 154} + Event_EventCloseClaimStatus = [8]byte{87, 68, 38, 194, 241, 155, 125, 107} + Event_EventCloseVestingEscrow = [8]byte{45, 141, 253, 209, 196, 133, 21, 204} + Event_EventCreateRootEscrow = [8]byte{105, 216, 97, 182, 27, 224, 199, 228} + Event_EventCreateVestingEscrow = [8]byte{248, 222, 89, 61, 170, 208, 131, 117} + Event_EventFundRootEscrow = [8]byte{74, 8, 68, 181, 198, 235, 138, 81} + Event_EventUpdateVestingEscrowRecipient = [8]byte{206, 218, 33, 65, 133, 237, 131, 57} +) + +// Instruction discriminators +var ( + Instruction_CancelVestingEscrow = [8]byte{217, 233, 13, 3, 143, 101, 53, 201} + Instruction_Claim = [8]byte{62, 198, 214, 193, 213, 159, 108, 210} + Instruction_ClaimV2 = [8]byte{229, 87, 46, 162, 21, 157, 231, 114} + Instruction_CloseVestingEscrow = [8]byte{221, 185, 95, 135, 136, 67, 252, 87} + Instruction_CreateRootEscrow = [8]byte{116, 212, 12, 188, 77, 226, 32, 201} + Instruction_CreateVestingEscrow = [8]byte{23, 100, 197, 94, 222, 153, 38, 90} + Instruction_CreateVestingEscrowFromRoot = [8]byte{6, 238, 161, 108, 252, 114, 246, 91} + Instruction_CreateVestingEscrowMetadata = [8]byte{93, 78, 33, 103, 173, 125, 70, 0} + Instruction_CreateVestingEscrowV2 = [8]byte{181, 155, 104, 183, 182, 128, 35, 47} + Instruction_FundRootEscrow = [8]byte{251, 106, 189, 200, 108, 15, 144, 95} + Instruction_UpdateVestingEscrowRecipient = [8]byte{26, 242, 127, 255, 237, 109, 47, 206} +) diff --git a/solana/spl/programs/meteora_locker/instructions.go b/solana/spl/programs/meteora_locker/instructions.go new file mode 100644 index 00000000..3516a104 --- /dev/null +++ b/solana/spl/programs/meteora_locker/instructions.go @@ -0,0 +1,911 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. +// This file contains instructions. + +package meteora_locker + +import ( + "bytes" + "fmt" + errors "github.com/gagliardetto/anchor-go/errors" + binary "github.com/gagliardetto/binary" + solanago "github.com/gagliardetto/solana-go" +) + +// Builds a "cancel_vesting_escrow" instruction. +// Cancel a vesting escrow. // - The claimable token will be transferred to recipient // - The remaining token will be transferred to the creator // This instruction supports both splToken and token2022 // # Arguments // // * ctx - The accounts needed by instruction. // * remaining_accounts_info: additional accounts needed by instruction // +func NewCancelVestingEscrowInstruction( + // Params: + remainingAccountsInfoParam *RemainingAccountsInfo, + + // Accounts: + escrowAccount solanago.PublicKey, + tokenMintAccount solanago.PublicKey, + escrowTokenAccount solanago.PublicKey, + creatorTokenAccount solanago.PublicKey, + recipientTokenAccount solanago.PublicKey, + rentReceiverAccount solanago.PublicKey, + signerAccount solanago.PublicKey, + memoProgramAccount solanago.PublicKey, + tokenProgramAccount solanago.PublicKey, + eventAuthorityAccount solanago.PublicKey, + programAccount solanago.PublicKey, +) (solanago.Instruction, error) { + buf__ := new(bytes.Buffer) + enc__ := binary.NewBorshEncoder(buf__) + + // Encode the instruction discriminator. + err := enc__.WriteBytes(Instruction_CancelVestingEscrow[:], false) + if err != nil { + return nil, fmt.Errorf("failed to write instruction discriminator: %w", err) + } + { + // Serialize `remainingAccountsInfoParam` (optional): + { + if remainingAccountsInfoParam == nil { + err = enc__.WriteOption(false) + if err != nil { + return nil, errors.NewOption("remainingAccountsInfoParam", fmt.Errorf("error while encoding optionality: %w", err)) + } + } else { + err = enc__.WriteOption(true) + if err != nil { + return nil, errors.NewOption("remainingAccountsInfoParam", fmt.Errorf("error while encoding optionality: %w", err)) + } + err = enc__.Encode(remainingAccountsInfoParam) + if err != nil { + return nil, errors.NewField("remainingAccountsInfoParam", err) + } + } + } + } + accounts__ := solanago.AccountMetaSlice{} + + // Add the accounts to the instruction. + { + // Account 0 "escrow": Writable, Non-signer, Required + // Escrow. + accounts__.Append(solanago.NewAccountMeta(escrowAccount, true, false)) + // Account 1 "token_mint": Writable, Non-signer, Required + // Mint. + accounts__.Append(solanago.NewAccountMeta(tokenMintAccount, true, false)) + // Account 2 "escrow_token": Writable, Non-signer, Required + // Escrow Token Account. + accounts__.Append(solanago.NewAccountMeta(escrowTokenAccount, true, false)) + // Account 3 "creator_token": Writable, Non-signer, Required + // Creator Token Account. + accounts__.Append(solanago.NewAccountMeta(creatorTokenAccount, true, false)) + // Account 4 "recipient_token": Writable, Non-signer, Required + // Receipient Token Account. + accounts__.Append(solanago.NewAccountMeta(recipientTokenAccount, true, false)) + // Account 5 "rent_receiver": Writable, Non-signer, Required + // CHECKED: The Token Account will receive the rent + accounts__.Append(solanago.NewAccountMeta(rentReceiverAccount, true, false)) + // Account 6 "signer": Writable, Signer, Required + // Signer. + accounts__.Append(solanago.NewAccountMeta(signerAccount, true, true)) + // Account 7 "memo_program": Read-only, Non-signer, Required, Address: MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr + // Memo program. + accounts__.Append(solanago.NewAccountMeta(memoProgramAccount, false, false)) + // Account 8 "token_program": Read-only, Non-signer, Required + // Token program. + accounts__.Append(solanago.NewAccountMeta(tokenProgramAccount, false, false)) + // Account 9 "event_authority": Read-only, Non-signer, Required + accounts__.Append(solanago.NewAccountMeta(eventAuthorityAccount, false, false)) + // Account 10 "program": Read-only, Non-signer, Required + accounts__.Append(solanago.NewAccountMeta(programAccount, false, false)) + } + + // Create the instruction. + return solanago.NewInstruction( + ProgramID, + accounts__, + buf__.Bytes(), + ), nil +} + +// Builds a "claim" instruction. +// Claim maximum amount from the vesting escrow // # Arguments // // * ctx - The accounts needed by instruction. // * max_amount - The maximum amount claimed by the recipient // +func NewClaimInstruction( + // Params: + maxAmountParam uint64, + + // Accounts: + escrowAccount solanago.PublicKey, + escrowTokenAccount solanago.PublicKey, + recipientAccount solanago.PublicKey, + recipientTokenAccount solanago.PublicKey, + tokenProgramAccount solanago.PublicKey, + eventAuthorityAccount solanago.PublicKey, + programAccount solanago.PublicKey, +) (solanago.Instruction, error) { + buf__ := new(bytes.Buffer) + enc__ := binary.NewBorshEncoder(buf__) + + // Encode the instruction discriminator. + err := enc__.WriteBytes(Instruction_Claim[:], false) + if err != nil { + return nil, fmt.Errorf("failed to write instruction discriminator: %w", err) + } + { + // Serialize `maxAmountParam`: + err = enc__.Encode(maxAmountParam) + if err != nil { + return nil, errors.NewField("maxAmountParam", err) + } + } + accounts__ := solanago.AccountMetaSlice{} + + // Add the accounts to the instruction. + { + // Account 0 "escrow": Writable, Non-signer, Required + // Escrow. + accounts__.Append(solanago.NewAccountMeta(escrowAccount, true, false)) + // Account 1 "escrow_token": Writable, Non-signer, Required + // Escrow Token Account. + accounts__.Append(solanago.NewAccountMeta(escrowTokenAccount, true, false)) + // Account 2 "recipient": Writable, Signer, Required + // Recipient. + accounts__.Append(solanago.NewAccountMeta(recipientAccount, true, true)) + // Account 3 "recipient_token": Writable, Non-signer, Required + // Recipient Token Account. + accounts__.Append(solanago.NewAccountMeta(recipientTokenAccount, true, false)) + // Account 4 "token_program": Read-only, Non-signer, Required, Address: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA + // Token program. + accounts__.Append(solanago.NewAccountMeta(tokenProgramAccount, false, false)) + // Account 5 "event_authority": Read-only, Non-signer, Required + accounts__.Append(solanago.NewAccountMeta(eventAuthorityAccount, false, false)) + // Account 6 "program": Read-only, Non-signer, Required + accounts__.Append(solanago.NewAccountMeta(programAccount, false, false)) + } + + // Create the instruction. + return solanago.NewInstruction( + ProgramID, + accounts__, + buf__.Bytes(), + ), nil +} + +// Builds a "claim_v2" instruction. +// Claim maximum amount from the vesting escrow // This instruction supports both splToken and token2022 // # Arguments // // * ctx - The accounts needed by instruction. // * max_amount - The maximum amount claimed by the recipient // * remaining_accounts_info: additional accounts needed by instruction // +func NewClaimV2Instruction( + // Params: + maxAmountParam uint64, + remainingAccountsInfoParam *RemainingAccountsInfo, + + // Accounts: + escrowAccount solanago.PublicKey, + tokenMintAccount solanago.PublicKey, + escrowTokenAccount solanago.PublicKey, + recipientAccount solanago.PublicKey, + recipientTokenAccount solanago.PublicKey, + memoProgramAccount solanago.PublicKey, + tokenProgramAccount solanago.PublicKey, + eventAuthorityAccount solanago.PublicKey, + programAccount solanago.PublicKey, +) (solanago.Instruction, error) { + buf__ := new(bytes.Buffer) + enc__ := binary.NewBorshEncoder(buf__) + + // Encode the instruction discriminator. + err := enc__.WriteBytes(Instruction_ClaimV2[:], false) + if err != nil { + return nil, fmt.Errorf("failed to write instruction discriminator: %w", err) + } + { + // Serialize `maxAmountParam`: + err = enc__.Encode(maxAmountParam) + if err != nil { + return nil, errors.NewField("maxAmountParam", err) + } + // Serialize `remainingAccountsInfoParam` (optional): + { + if remainingAccountsInfoParam == nil { + err = enc__.WriteOption(false) + if err != nil { + return nil, errors.NewOption("remainingAccountsInfoParam", fmt.Errorf("error while encoding optionality: %w", err)) + } + } else { + err = enc__.WriteOption(true) + if err != nil { + return nil, errors.NewOption("remainingAccountsInfoParam", fmt.Errorf("error while encoding optionality: %w", err)) + } + err = enc__.Encode(remainingAccountsInfoParam) + if err != nil { + return nil, errors.NewField("remainingAccountsInfoParam", err) + } + } + } + } + accounts__ := solanago.AccountMetaSlice{} + + // Add the accounts to the instruction. + { + // Account 0 "escrow": Writable, Non-signer, Required + // Escrow. + accounts__.Append(solanago.NewAccountMeta(escrowAccount, true, false)) + // Account 1 "token_mint": Read-only, Non-signer, Required + // Mint. + accounts__.Append(solanago.NewAccountMeta(tokenMintAccount, false, false)) + // Account 2 "escrow_token": Writable, Non-signer, Required + // Escrow Token Account. + accounts__.Append(solanago.NewAccountMeta(escrowTokenAccount, true, false)) + // Account 3 "recipient": Writable, Signer, Required + // Recipient. + accounts__.Append(solanago.NewAccountMeta(recipientAccount, true, true)) + // Account 4 "recipient_token": Writable, Non-signer, Required + // Recipient Token Account. + accounts__.Append(solanago.NewAccountMeta(recipientTokenAccount, true, false)) + // Account 5 "memo_program": Read-only, Non-signer, Required, Address: MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr + // Memo program. + accounts__.Append(solanago.NewAccountMeta(memoProgramAccount, false, false)) + // Account 6 "token_program": Read-only, Non-signer, Required + // Token program. + accounts__.Append(solanago.NewAccountMeta(tokenProgramAccount, false, false)) + // Account 7 "event_authority": Read-only, Non-signer, Required + accounts__.Append(solanago.NewAccountMeta(eventAuthorityAccount, false, false)) + // Account 8 "program": Read-only, Non-signer, Required + accounts__.Append(solanago.NewAccountMeta(programAccount, false, false)) + } + + // Create the instruction. + return solanago.NewInstruction( + ProgramID, + accounts__, + buf__.Bytes(), + ), nil +} + +// Builds a "close_vesting_escrow" instruction. +// Close vesting escrow // - Close vesting escrow and escrow ATA and escrow metadata if recipient already claimed all tokens // - Rent receiver must be escrow's creator // This instruction supports both splToken and token2022 // # Arguments // // * ctx - The accounts needed by instruction. // * remaining_accounts_info: additional accounts needed by instruction // +func NewCloseVestingEscrowInstruction( + // Params: + remainingAccountsInfoParam *RemainingAccountsInfo, + + // Accounts: + escrowAccount solanago.PublicKey, + escrowMetadataAccount solanago.PublicKey, + tokenMintAccount solanago.PublicKey, + escrowTokenAccount solanago.PublicKey, + creatorTokenAccount solanago.PublicKey, + creatorAccount solanago.PublicKey, + tokenProgramAccount solanago.PublicKey, + memoProgramAccount solanago.PublicKey, + eventAuthorityAccount solanago.PublicKey, + programAccount solanago.PublicKey, +) (solanago.Instruction, error) { + buf__ := new(bytes.Buffer) + enc__ := binary.NewBorshEncoder(buf__) + + // Encode the instruction discriminator. + err := enc__.WriteBytes(Instruction_CloseVestingEscrow[:], false) + if err != nil { + return nil, fmt.Errorf("failed to write instruction discriminator: %w", err) + } + { + // Serialize `remainingAccountsInfoParam` (optional): + { + if remainingAccountsInfoParam == nil { + err = enc__.WriteOption(false) + if err != nil { + return nil, errors.NewOption("remainingAccountsInfoParam", fmt.Errorf("error while encoding optionality: %w", err)) + } + } else { + err = enc__.WriteOption(true) + if err != nil { + return nil, errors.NewOption("remainingAccountsInfoParam", fmt.Errorf("error while encoding optionality: %w", err)) + } + err = enc__.Encode(remainingAccountsInfoParam) + if err != nil { + return nil, errors.NewField("remainingAccountsInfoParam", err) + } + } + } + } + accounts__ := solanago.AccountMetaSlice{} + + // Add the accounts to the instruction. + { + // Account 0 "escrow": Writable, Non-signer, Required + // Escrow. + accounts__.Append(solanago.NewAccountMeta(escrowAccount, true, false)) + // Account 1 "escrow_metadata": Writable, Non-signer, Required + accounts__.Append(solanago.NewAccountMeta(escrowMetadataAccount, true, false)) + // Account 2 "token_mint": Writable, Non-signer, Required + // Mint. + accounts__.Append(solanago.NewAccountMeta(tokenMintAccount, true, false)) + // Account 3 "escrow_token": Writable, Non-signer, Required + accounts__.Append(solanago.NewAccountMeta(escrowTokenAccount, true, false)) + // Account 4 "creator_token": Writable, Non-signer, Required + accounts__.Append(solanago.NewAccountMeta(creatorTokenAccount, true, false)) + // Account 5 "creator": Writable, Signer, Required + // Creator. + accounts__.Append(solanago.NewAccountMeta(creatorAccount, true, true)) + // Account 6 "token_program": Read-only, Non-signer, Required + // Token program. + accounts__.Append(solanago.NewAccountMeta(tokenProgramAccount, false, false)) + // Account 7 "memo_program": Read-only, Non-signer, Required, Address: MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr + // Memo program. + accounts__.Append(solanago.NewAccountMeta(memoProgramAccount, false, false)) + // Account 8 "event_authority": Read-only, Non-signer, Required + accounts__.Append(solanago.NewAccountMeta(eventAuthorityAccount, false, false)) + // Account 9 "program": Read-only, Non-signer, Required + accounts__.Append(solanago.NewAccountMeta(programAccount, false, false)) + } + + // Create the instruction. + return solanago.NewInstruction( + ProgramID, + accounts__, + buf__.Bytes(), + ), nil +} + +// Builds a "create_root_escrow" instruction. +// Create root escrow +func NewCreateRootEscrowInstruction( + // Params: + paramsParam CreateRootEscrowParameters, + + // Accounts: + baseAccount solanago.PublicKey, + rootEscrowAccount solanago.PublicKey, + tokenMintAccount solanago.PublicKey, + payerAccount solanago.PublicKey, + creatorAccount solanago.PublicKey, + systemProgramAccount solanago.PublicKey, + eventAuthorityAccount solanago.PublicKey, + programAccount solanago.PublicKey, +) (solanago.Instruction, error) { + buf__ := new(bytes.Buffer) + enc__ := binary.NewBorshEncoder(buf__) + + // Encode the instruction discriminator. + err := enc__.WriteBytes(Instruction_CreateRootEscrow[:], false) + if err != nil { + return nil, fmt.Errorf("failed to write instruction discriminator: %w", err) + } + { + // Serialize `paramsParam`: + err = enc__.Encode(paramsParam) + if err != nil { + return nil, errors.NewField("paramsParam", err) + } + } + accounts__ := solanago.AccountMetaSlice{} + + // Add the accounts to the instruction. + { + // Account 0 "base": Read-only, Signer, Required + accounts__.Append(solanago.NewAccountMeta(baseAccount, false, true)) + // Account 1 "root_escrow": Writable, Non-signer, Required + // Root Escrow. + accounts__.Append(solanago.NewAccountMeta(rootEscrowAccount, true, false)) + // Account 2 "token_mint": Read-only, Non-signer, Required + accounts__.Append(solanago.NewAccountMeta(tokenMintAccount, false, false)) + // Account 3 "payer": Writable, Signer, Required + // Payer. + accounts__.Append(solanago.NewAccountMeta(payerAccount, true, true)) + // Account 4 "creator": Read-only, Non-signer, Required + accounts__.Append(solanago.NewAccountMeta(creatorAccount, false, false)) + // Account 5 "system_program": Read-only, Non-signer, Required + // System program. + accounts__.Append(solanago.NewAccountMeta(systemProgramAccount, false, false)) + // Account 6 "event_authority": Read-only, Non-signer, Required + accounts__.Append(solanago.NewAccountMeta(eventAuthorityAccount, false, false)) + // Account 7 "program": Read-only, Non-signer, Required + accounts__.Append(solanago.NewAccountMeta(programAccount, false, false)) + } + + // Create the instruction. + return solanago.NewInstruction( + ProgramID, + accounts__, + buf__.Bytes(), + ), nil +} + +// Builds a "create_vesting_escrow" instruction. +// Create a vesting escrow for the given params // # Arguments // // * ctx - The accounts needed by instruction. // * params - The params needed by instruction. // * vesting_start_time - The creation time of this escrow // * cliff_time - Trade cliff time of the escrow // * frequency - How frequent the claimable amount will be updated // * cliff_unlock_amount - The amount unlocked after cliff time // * amount_per_period - The amount unlocked per vesting period // * number_of_period - The total number of vesting period // * update_recipient_mode - Decide who can update the recipient of the escrow // * cancel_mode - Decide who can cancel the the escrow // +func NewCreateVestingEscrowInstruction( + // Params: + paramsParam CreateVestingEscrowParameters, + + // Accounts: + baseAccount solanago.PublicKey, + escrowAccount solanago.PublicKey, + escrowTokenAccount solanago.PublicKey, + senderAccount solanago.PublicKey, + senderTokenAccount solanago.PublicKey, + recipientAccount solanago.PublicKey, + tokenProgramAccount solanago.PublicKey, + systemProgramAccount solanago.PublicKey, + eventAuthorityAccount solanago.PublicKey, + programAccount solanago.PublicKey, +) (solanago.Instruction, error) { + buf__ := new(bytes.Buffer) + enc__ := binary.NewBorshEncoder(buf__) + + // Encode the instruction discriminator. + err := enc__.WriteBytes(Instruction_CreateVestingEscrow[:], false) + if err != nil { + return nil, fmt.Errorf("failed to write instruction discriminator: %w", err) + } + { + // Serialize `paramsParam`: + err = enc__.Encode(paramsParam) + if err != nil { + return nil, errors.NewField("paramsParam", err) + } + } + accounts__ := solanago.AccountMetaSlice{} + + // Add the accounts to the instruction. + { + // Account 0 "base": Writable, Signer, Required + // Base. + accounts__.Append(solanago.NewAccountMeta(baseAccount, true, true)) + // Account 1 "escrow": Writable, Non-signer, Required + // Escrow. + accounts__.Append(solanago.NewAccountMeta(escrowAccount, true, false)) + // Account 2 "escrow_token": Writable, Non-signer, Required + // Escrow Token Account. + accounts__.Append(solanago.NewAccountMeta(escrowTokenAccount, true, false)) + // Account 3 "sender": Writable, Signer, Required + // Sender. + accounts__.Append(solanago.NewAccountMeta(senderAccount, true, true)) + // Account 4 "sender_token": Writable, Non-signer, Required + // Sender Token Account. + accounts__.Append(solanago.NewAccountMeta(senderTokenAccount, true, false)) + // Account 5 "recipient": Read-only, Non-signer, Required + accounts__.Append(solanago.NewAccountMeta(recipientAccount, false, false)) + // Account 6 "token_program": Read-only, Non-signer, Required, Address: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA + // Token program. + accounts__.Append(solanago.NewAccountMeta(tokenProgramAccount, false, false)) + // Account 7 "system_program": Read-only, Non-signer, Required + // system program. + accounts__.Append(solanago.NewAccountMeta(systemProgramAccount, false, false)) + // Account 8 "event_authority": Read-only, Non-signer, Required + accounts__.Append(solanago.NewAccountMeta(eventAuthorityAccount, false, false)) + // Account 9 "program": Read-only, Non-signer, Required + accounts__.Append(solanago.NewAccountMeta(programAccount, false, false)) + } + + // Create the instruction. + return solanago.NewInstruction( + ProgramID, + accounts__, + buf__.Bytes(), + ), nil +} + +// Builds a "create_vesting_escrow_from_root" instruction. +// Crate vesting escrow from root +func NewCreateVestingEscrowFromRootInstruction( + // Params: + paramsParam CreateVestingEscrowFromRootParams, + proofParam [][32]uint8, + remainingAccountsInfoParam *RemainingAccountsInfo, + + // Accounts: + rootEscrowAccount solanago.PublicKey, + baseAccount solanago.PublicKey, + escrowAccount solanago.PublicKey, + escrowTokenAccount solanago.PublicKey, + rootEscrowTokenAccount solanago.PublicKey, + tokenMintAccount solanago.PublicKey, + payerAccount solanago.PublicKey, + recipientAccount solanago.PublicKey, + systemProgramAccount solanago.PublicKey, + tokenProgramAccount solanago.PublicKey, + associatedTokenProgramAccount solanago.PublicKey, + eventAuthorityAccount solanago.PublicKey, + programAccount solanago.PublicKey, +) (solanago.Instruction, error) { + buf__ := new(bytes.Buffer) + enc__ := binary.NewBorshEncoder(buf__) + + // Encode the instruction discriminator. + err := enc__.WriteBytes(Instruction_CreateVestingEscrowFromRoot[:], false) + if err != nil { + return nil, fmt.Errorf("failed to write instruction discriminator: %w", err) + } + { + // Serialize `paramsParam`: + err = enc__.Encode(paramsParam) + if err != nil { + return nil, errors.NewField("paramsParam", err) + } + // Serialize `proofParam`: + err = enc__.Encode(proofParam) + if err != nil { + return nil, errors.NewField("proofParam", err) + } + // Serialize `remainingAccountsInfoParam` (optional): + { + if remainingAccountsInfoParam == nil { + err = enc__.WriteOption(false) + if err != nil { + return nil, errors.NewOption("remainingAccountsInfoParam", fmt.Errorf("error while encoding optionality: %w", err)) + } + } else { + err = enc__.WriteOption(true) + if err != nil { + return nil, errors.NewOption("remainingAccountsInfoParam", fmt.Errorf("error while encoding optionality: %w", err)) + } + err = enc__.Encode(remainingAccountsInfoParam) + if err != nil { + return nil, errors.NewField("remainingAccountsInfoParam", err) + } + } + } + } + accounts__ := solanago.AccountMetaSlice{} + + // Add the accounts to the instruction. + { + // Account 0 "root_escrow": Writable, Non-signer, Required + // Root Escrow. + accounts__.Append(solanago.NewAccountMeta(rootEscrowAccount, true, false)) + // Account 1 "base": Read-only, Non-signer, Required + accounts__.Append(solanago.NewAccountMeta(baseAccount, false, false)) + // Account 2 "escrow": Writable, Non-signer, Required + // Escrow. + accounts__.Append(solanago.NewAccountMeta(escrowAccount, true, false)) + // Account 3 "escrow_token": Writable, Non-signer, Required + // Escrow Token Account. + accounts__.Append(solanago.NewAccountMeta(escrowTokenAccount, true, false)) + // Account 4 "root_escrow_token": Writable, Non-signer, Required + accounts__.Append(solanago.NewAccountMeta(rootEscrowTokenAccount, true, false)) + // Account 5 "token_mint": Read-only, Non-signer, Required + // Mint. + accounts__.Append(solanago.NewAccountMeta(tokenMintAccount, false, false)) + // Account 6 "payer": Writable, Signer, Required + // Rent Payer + accounts__.Append(solanago.NewAccountMeta(payerAccount, true, true)) + // Account 7 "recipient": Read-only, Non-signer, Required + accounts__.Append(solanago.NewAccountMeta(recipientAccount, false, false)) + // Account 8 "system_program": Read-only, Non-signer, Required + // system program. + accounts__.Append(solanago.NewAccountMeta(systemProgramAccount, false, false)) + // Account 9 "token_program": Read-only, Non-signer, Required + // Token program. + accounts__.Append(solanago.NewAccountMeta(tokenProgramAccount, false, false)) + // Account 10 "associated_token_program": Read-only, Non-signer, Required, Address: ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL + accounts__.Append(solanago.NewAccountMeta(associatedTokenProgramAccount, false, false)) + // Account 11 "event_authority": Read-only, Non-signer, Required + accounts__.Append(solanago.NewAccountMeta(eventAuthorityAccount, false, false)) + // Account 12 "program": Read-only, Non-signer, Required + accounts__.Append(solanago.NewAccountMeta(programAccount, false, false)) + } + + // Create the instruction. + return solanago.NewInstruction( + ProgramID, + accounts__, + buf__.Bytes(), + ), nil +} + +// Builds a "create_vesting_escrow_metadata" instruction. +// Create vesting escrow metadata // # Arguments // // * ctx - The accounts needed by instruction. // * params - The params needed by instruction. // * name - The name of the vesting escrow // * description - The description of the vesting escrow // * creator_email - The email of the creator // * recipient_email - The email of the recipient // +func NewCreateVestingEscrowMetadataInstruction( + // Params: + paramsParam CreateVestingEscrowMetadataParameters, + + // Accounts: + escrowAccount solanago.PublicKey, + creatorAccount solanago.PublicKey, + escrowMetadataAccount solanago.PublicKey, + payerAccount solanago.PublicKey, + systemProgramAccount solanago.PublicKey, +) (solanago.Instruction, error) { + buf__ := new(bytes.Buffer) + enc__ := binary.NewBorshEncoder(buf__) + + // Encode the instruction discriminator. + err := enc__.WriteBytes(Instruction_CreateVestingEscrowMetadata[:], false) + if err != nil { + return nil, fmt.Errorf("failed to write instruction discriminator: %w", err) + } + { + // Serialize `paramsParam`: + err = enc__.Encode(paramsParam) + if err != nil { + return nil, errors.NewField("paramsParam", err) + } + } + accounts__ := solanago.AccountMetaSlice{} + + // Add the accounts to the instruction. + { + // Account 0 "escrow": Writable, Non-signer, Required + // The [Escrow]. + accounts__.Append(solanago.NewAccountMeta(escrowAccount, true, false)) + // Account 1 "creator": Read-only, Signer, Required + // Creator of the escrow. + accounts__.Append(solanago.NewAccountMeta(creatorAccount, false, true)) + // Account 2 "escrow_metadata": Writable, Non-signer, Required + // The [ProposalMeta]. + accounts__.Append(solanago.NewAccountMeta(escrowMetadataAccount, true, false)) + // Account 3 "payer": Writable, Signer, Required + // Payer of the [ProposalMeta]. + accounts__.Append(solanago.NewAccountMeta(payerAccount, true, true)) + // Account 4 "system_program": Read-only, Non-signer, Required + // system program. + accounts__.Append(solanago.NewAccountMeta(systemProgramAccount, false, false)) + } + + // Create the instruction. + return solanago.NewInstruction( + ProgramID, + accounts__, + buf__.Bytes(), + ), nil +} + +// Builds a "create_vesting_escrow_v2" instruction. +// Create a vesting escrow for the given params // This instruction supports both splToken and token2022 // # Arguments // // * ctx - The accounts needed by instruction. // * params - The params needed by instruction. // * vesting_start_time - The creation time of this escrow // * cliff_time - Trade cliff time of the escrow // * frequency - How frequent the claimable amount will be updated // * cliff_unlock_amount - The amount unlocked after cliff time // * amount_per_period - The amount unlocked per vesting period // * number_of_period - The total number of vesting period // * update_recipient_mode - Decide who can update the recipient of the escrow // * cancel_mode - Decide who can cancel the the escrow // * remaining_accounts_info: additional accounts needed by instruction // +func NewCreateVestingEscrowV2Instruction( + // Params: + paramsParam CreateVestingEscrowParameters, + remainingAccountsInfoParam *RemainingAccountsInfo, + + // Accounts: + baseAccount solanago.PublicKey, + escrowAccount solanago.PublicKey, + tokenMintAccount solanago.PublicKey, + escrowTokenAccount solanago.PublicKey, + senderAccount solanago.PublicKey, + senderTokenAccount solanago.PublicKey, + recipientAccount solanago.PublicKey, + tokenProgramAccount solanago.PublicKey, + systemProgramAccount solanago.PublicKey, + eventAuthorityAccount solanago.PublicKey, + programAccount solanago.PublicKey, +) (solanago.Instruction, error) { + buf__ := new(bytes.Buffer) + enc__ := binary.NewBorshEncoder(buf__) + + // Encode the instruction discriminator. + err := enc__.WriteBytes(Instruction_CreateVestingEscrowV2[:], false) + if err != nil { + return nil, fmt.Errorf("failed to write instruction discriminator: %w", err) + } + { + // Serialize `paramsParam`: + err = enc__.Encode(paramsParam) + if err != nil { + return nil, errors.NewField("paramsParam", err) + } + // Serialize `remainingAccountsInfoParam` (optional): + { + if remainingAccountsInfoParam == nil { + err = enc__.WriteOption(false) + if err != nil { + return nil, errors.NewOption("remainingAccountsInfoParam", fmt.Errorf("error while encoding optionality: %w", err)) + } + } else { + err = enc__.WriteOption(true) + if err != nil { + return nil, errors.NewOption("remainingAccountsInfoParam", fmt.Errorf("error while encoding optionality: %w", err)) + } + err = enc__.Encode(remainingAccountsInfoParam) + if err != nil { + return nil, errors.NewField("remainingAccountsInfoParam", err) + } + } + } + } + accounts__ := solanago.AccountMetaSlice{} + + // Add the accounts to the instruction. + { + // Account 0 "base": Writable, Signer, Required + // Base. + accounts__.Append(solanago.NewAccountMeta(baseAccount, true, true)) + // Account 1 "escrow": Writable, Non-signer, Required + // Escrow. + accounts__.Append(solanago.NewAccountMeta(escrowAccount, true, false)) + // Account 2 "token_mint": Read-only, Non-signer, Required + accounts__.Append(solanago.NewAccountMeta(tokenMintAccount, false, false)) + // Account 3 "escrow_token": Writable, Non-signer, Required + // Escrow Token Account. + accounts__.Append(solanago.NewAccountMeta(escrowTokenAccount, true, false)) + // Account 4 "sender": Writable, Signer, Required + // Sender. + accounts__.Append(solanago.NewAccountMeta(senderAccount, true, true)) + // Account 5 "sender_token": Writable, Non-signer, Required + // Sender Token Account. + accounts__.Append(solanago.NewAccountMeta(senderTokenAccount, true, false)) + // Account 6 "recipient": Read-only, Non-signer, Required + accounts__.Append(solanago.NewAccountMeta(recipientAccount, false, false)) + // Account 7 "token_program": Read-only, Non-signer, Required + // Token program. + accounts__.Append(solanago.NewAccountMeta(tokenProgramAccount, false, false)) + // Account 8 "system_program": Read-only, Non-signer, Required + // system program. + accounts__.Append(solanago.NewAccountMeta(systemProgramAccount, false, false)) + // Account 9 "event_authority": Read-only, Non-signer, Required + accounts__.Append(solanago.NewAccountMeta(eventAuthorityAccount, false, false)) + // Account 10 "program": Read-only, Non-signer, Required + accounts__.Append(solanago.NewAccountMeta(programAccount, false, false)) + } + + // Create the instruction. + return solanago.NewInstruction( + ProgramID, + accounts__, + buf__.Bytes(), + ), nil +} + +// Builds a "fund_root_escrow" instruction. +// Fund root escrow +func NewFundRootEscrowInstruction( + // Params: + maxAmountParam uint64, + remainingAccountsInfoParam *RemainingAccountsInfo, + + // Accounts: + rootEscrowAccount solanago.PublicKey, + tokenMintAccount solanago.PublicKey, + rootEscrowTokenAccount solanago.PublicKey, + payerAccount solanago.PublicKey, + payerTokenAccount solanago.PublicKey, + tokenProgramAccount solanago.PublicKey, + systemProgramAccount solanago.PublicKey, + associatedTokenProgramAccount solanago.PublicKey, + eventAuthorityAccount solanago.PublicKey, + programAccount solanago.PublicKey, +) (solanago.Instruction, error) { + buf__ := new(bytes.Buffer) + enc__ := binary.NewBorshEncoder(buf__) + + // Encode the instruction discriminator. + err := enc__.WriteBytes(Instruction_FundRootEscrow[:], false) + if err != nil { + return nil, fmt.Errorf("failed to write instruction discriminator: %w", err) + } + { + // Serialize `maxAmountParam`: + err = enc__.Encode(maxAmountParam) + if err != nil { + return nil, errors.NewField("maxAmountParam", err) + } + // Serialize `remainingAccountsInfoParam` (optional): + { + if remainingAccountsInfoParam == nil { + err = enc__.WriteOption(false) + if err != nil { + return nil, errors.NewOption("remainingAccountsInfoParam", fmt.Errorf("error while encoding optionality: %w", err)) + } + } else { + err = enc__.WriteOption(true) + if err != nil { + return nil, errors.NewOption("remainingAccountsInfoParam", fmt.Errorf("error while encoding optionality: %w", err)) + } + err = enc__.Encode(remainingAccountsInfoParam) + if err != nil { + return nil, errors.NewField("remainingAccountsInfoParam", err) + } + } + } + } + accounts__ := solanago.AccountMetaSlice{} + + // Add the accounts to the instruction. + { + // Account 0 "root_escrow": Writable, Non-signer, Required + // Root Escrow. + accounts__.Append(solanago.NewAccountMeta(rootEscrowAccount, true, false)) + // Account 1 "token_mint": Read-only, Non-signer, Required + accounts__.Append(solanago.NewAccountMeta(tokenMintAccount, false, false)) + // Account 2 "root_escrow_token": Writable, Non-signer, Required + // Escrow Token Account. + accounts__.Append(solanago.NewAccountMeta(rootEscrowTokenAccount, true, false)) + // Account 3 "payer": Writable, Signer, Required + // Payer. + accounts__.Append(solanago.NewAccountMeta(payerAccount, true, true)) + // Account 4 "payer_token": Writable, Non-signer, Required + // Payer Token Account. + accounts__.Append(solanago.NewAccountMeta(payerTokenAccount, true, false)) + // Account 5 "token_program": Read-only, Non-signer, Required + // Token program. + accounts__.Append(solanago.NewAccountMeta(tokenProgramAccount, false, false)) + // Account 6 "system_program": Read-only, Non-signer, Required + // system program. + accounts__.Append(solanago.NewAccountMeta(systemProgramAccount, false, false)) + // Account 7 "associated_token_program": Read-only, Non-signer, Required, Address: ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL + accounts__.Append(solanago.NewAccountMeta(associatedTokenProgramAccount, false, false)) + // Account 8 "event_authority": Read-only, Non-signer, Required + accounts__.Append(solanago.NewAccountMeta(eventAuthorityAccount, false, false)) + // Account 9 "program": Read-only, Non-signer, Required + accounts__.Append(solanago.NewAccountMeta(programAccount, false, false)) + } + + // Create the instruction. + return solanago.NewInstruction( + ProgramID, + accounts__, + buf__.Bytes(), + ), nil +} + +// Builds a "update_vesting_escrow_recipient" instruction. +// Update vesting escrow metadata // # Arguments // // * ctx - The accounts needed by instruction. // * new_recipient - The address of the new recipient // * new_recipient_email - The email of the new recipient // +func NewUpdateVestingEscrowRecipientInstruction( + // Params: + newRecipientParam solanago.PublicKey, + newRecipientEmailParam *string, + + // Accounts: + escrowAccount solanago.PublicKey, + escrowMetadataAccount solanago.PublicKey, + signerAccount solanago.PublicKey, + systemProgramAccount solanago.PublicKey, + eventAuthorityAccount solanago.PublicKey, + programAccount solanago.PublicKey, +) (solanago.Instruction, error) { + buf__ := new(bytes.Buffer) + enc__ := binary.NewBorshEncoder(buf__) + + // Encode the instruction discriminator. + err := enc__.WriteBytes(Instruction_UpdateVestingEscrowRecipient[:], false) + if err != nil { + return nil, fmt.Errorf("failed to write instruction discriminator: %w", err) + } + { + // Serialize `newRecipientParam`: + err = enc__.Encode(newRecipientParam) + if err != nil { + return nil, errors.NewField("newRecipientParam", err) + } + // Serialize `newRecipientEmailParam` (optional): + { + if newRecipientEmailParam == nil { + err = enc__.WriteOption(false) + if err != nil { + return nil, errors.NewOption("newRecipientEmailParam", fmt.Errorf("error while encoding optionality: %w", err)) + } + } else { + err = enc__.WriteOption(true) + if err != nil { + return nil, errors.NewOption("newRecipientEmailParam", fmt.Errorf("error while encoding optionality: %w", err)) + } + err = enc__.Encode(newRecipientEmailParam) + if err != nil { + return nil, errors.NewField("newRecipientEmailParam", err) + } + } + } + } + accounts__ := solanago.AccountMetaSlice{} + + // Add the accounts to the instruction. + { + // Account 0 "escrow": Writable, Non-signer, Required + // Escrow. + accounts__.Append(solanago.NewAccountMeta(escrowAccount, true, false)) + // Account 1 "escrow_metadata": Writable, Non-signer, Optional + // Escrow metadata. + accounts__.Append(solanago.NewAccountMeta(escrowMetadataAccount, true, false)) + // Account 2 "signer": Writable, Signer, Required + // Signer. + accounts__.Append(solanago.NewAccountMeta(signerAccount, true, true)) + // Account 3 "system_program": Read-only, Non-signer, Required + // system program. + accounts__.Append(solanago.NewAccountMeta(systemProgramAccount, false, false)) + // Account 4 "event_authority": Read-only, Non-signer, Required + accounts__.Append(solanago.NewAccountMeta(eventAuthorityAccount, false, false)) + // Account 5 "program": Read-only, Non-signer, Required + accounts__.Append(solanago.NewAccountMeta(programAccount, false, false)) + } + + // Create the instruction. + return solanago.NewInstruction( + ProgramID, + accounts__, + buf__.Bytes(), + ), nil +} diff --git a/solana/spl/programs/meteora_locker/program-id.go b/solana/spl/programs/meteora_locker/program-id.go new file mode 100644 index 00000000..5b654d50 --- /dev/null +++ b/solana/spl/programs/meteora_locker/program-id.go @@ -0,0 +1,8 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. +// This file contains the program ID. + +package meteora_locker + +import solanago "github.com/gagliardetto/solana-go" + +var ProgramID = solanago.MustPublicKeyFromBase58("LocpQgucEQHbqNABEYvBvwoxCPsSbG91A1QaQhQQqjn") diff --git a/solana/spl/programs/meteora_locker/types.go b/solana/spl/programs/meteora_locker/types.go new file mode 100644 index 00000000..34e274e2 --- /dev/null +++ b/solana/spl/programs/meteora_locker/types.go @@ -0,0 +1,195 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. +// This file contains parsers for the types defined in the IDL. + +package meteora_locker + +import ( + binary "github.com/gagliardetto/binary" + solanago "github.com/gagliardetto/solana-go" +) + +type AccountsType binary.BorshEnum + +const ( + AccountsType_TransferHookEscrow AccountsType = iota +) + +func (value AccountsType) String() string { + switch value { + case AccountsType_TransferHookEscrow: + return "TransferHookEscrow" + default: + return "" + } +} + +type CreateRootEscrowParameters struct { + MaxClaimAmount uint64 `json:"maxClaimAmount"` + MaxEscrow uint64 `json:"maxEscrow"` + Version uint64 `json:"version"` + Root [32]uint8 `json:"root"` +} + +type CreateVestingEscrowFromRootParams struct { + VestingStartTime uint64 `json:"vestingStartTime"` + CliffTime uint64 `json:"cliffTime"` + Frequency uint64 `json:"frequency"` + CliffUnlockAmount uint64 `json:"cliffUnlockAmount"` + AmountPerPeriod uint64 `json:"amountPerPeriod"` + NumberOfPeriod uint64 `json:"numberOfPeriod"` + UpdateRecipientMode uint8 `json:"updateRecipientMode"` + CancelMode uint8 `json:"cancelMode"` +} + +type CreateVestingEscrowMetadataParameters struct { + Name string `json:"name"` + Description string `json:"description"` + CreatorEmail string `json:"creatorEmail"` + RecipientEmail string `json:"recipientEmail"` +} + +type CreateVestingEscrowParameters struct { + VestingStartTime uint64 `json:"vestingStartTime"` + CliffTime uint64 `json:"cliffTime"` + Frequency uint64 `json:"frequency"` + CliffUnlockAmount uint64 `json:"cliffUnlockAmount"` + AmountPerPeriod uint64 `json:"amountPerPeriod"` + NumberOfPeriod uint64 `json:"numberOfPeriod"` + UpdateRecipientMode uint8 `json:"updateRecipientMode"` + CancelMode uint8 `json:"cancelMode"` +} + +type EventCancelVestingEscrow struct { + Escrow solanago.PublicKey `json:"escrow"` + Signer solanago.PublicKey `json:"signer"` + ClaimableAmount uint64 `json:"claimableAmount"` + RemainingAmount uint64 `json:"remainingAmount"` + CancelledAt uint64 `json:"cancelledAt"` +} + +type EventCancelVestingEscrowV3 struct { + Escrow solanago.PublicKey `json:"escrow"` + Signer solanago.PublicKey `json:"signer"` + RemainingAmount uint64 `json:"remainingAmount"` + CancelledAt uint64 `json:"cancelledAt"` +} + +type EventClaim struct { + Amount uint64 `json:"amount"` + CurrentTs uint64 `json:"currentTs"` + Escrow solanago.PublicKey `json:"escrow"` +} + +type EventClaimV3 struct { + Amount uint64 `json:"amount"` + CurrentTs uint64 `json:"currentTs"` + Escrow solanago.PublicKey `json:"escrow"` + VestingStartTime uint64 `json:"vestingStartTime"` + CliffTime uint64 `json:"cliffTime"` + Frequency uint64 `json:"frequency"` + CliffUnlockAmount uint64 `json:"cliffUnlockAmount"` + AmountPerPeriod uint64 `json:"amountPerPeriod"` + NumberOfPeriod uint64 `json:"numberOfPeriod"` + Recipient solanago.PublicKey `json:"recipient"` +} +type EventCloseClaimStatus struct { + Escrow solanago.PublicKey `json:"escrow"` + Recipient solanago.PublicKey `json:"recipient"` + RentReceiver solanago.PublicKey `json:"rentReceiver"` +} +type EventCloseVestingEscrow struct { + Escrow solanago.PublicKey `json:"escrow"` +} + +type EventCreateRootEscrow struct { + RootEscrow solanago.PublicKey `json:"rootEscrow"` + MaxClaimAmount uint64 `json:"maxClaimAmount"` + MaxEscrow uint64 `json:"maxEscrow"` + Version uint64 `json:"version"` + Root [32]uint8 `json:"root"` +} + +type EventCreateVestingEscrow struct { + VestingStartTime uint64 `json:"vestingStartTime"` + CliffTime uint64 `json:"cliffTime"` + Frequency uint64 `json:"frequency"` + CliffUnlockAmount uint64 `json:"cliffUnlockAmount"` + AmountPerPeriod uint64 `json:"amountPerPeriod"` + NumberOfPeriod uint64 `json:"numberOfPeriod"` + UpdateRecipientMode uint8 `json:"updateRecipientMode"` + CancelMode uint8 `json:"cancelMode"` + Recipient solanago.PublicKey `json:"recipient"` + Escrow solanago.PublicKey `json:"escrow"` +} + +type EventFundRootEscrow struct { + RootEscrow solanago.PublicKey `json:"rootEscrow"` + FundedAmount uint64 `json:"fundedAmount"` +} + +type EventUpdateVestingEscrowRecipient struct { + Escrow solanago.PublicKey `json:"escrow"` + OldRecipient solanago.PublicKey `json:"oldRecipient"` + NewRecipient solanago.PublicKey `json:"newRecipient"` + Signer solanago.PublicKey `json:"signer"` +} + +type RemainingAccountsInfo struct { + Slices []RemainingAccountsSlice `json:"slices"` +} + +type RemainingAccountsSlice struct { + AccountsType AccountsType `json:"accountsType"` + Length uint8 `json:"length"` +} + +type RootEscrow struct { + Discriminator [8]uint8 `json:"discriminator"` + TokenMint solanago.PublicKey `json:"tokenMint"` + Creator solanago.PublicKey `json:"creator"` + Base solanago.PublicKey `json:"base"` + Root [32]uint8 `json:"root"` + Bump uint8 `json:"bump"` + TokenProgramFlag uint8 `json:"tokenProgramFlag"` + Padding0 [6]uint8 `json:"padding0"` + MaxClaimAmount uint64 `json:"maxClaimAmount"` + MaxEscrow uint64 `json:"maxEscrow"` + TotalFundedAmount uint64 `json:"totalFundedAmount"` + TotalEscrowCreated uint64 `json:"totalEscrowCreated"` + TotalDistributeAmount uint64 `json:"totalDistributeAmount"` + Version uint64 `json:"version"` + Padding uint64 `json:"padding"` + Buffer [5]binary.Uint128 `json:"buffer"` +} + +type VestingEscrow struct { + Discriminator [8]uint8 `json:"discriminator"` + Recipient solanago.PublicKey `json:"recipient"` + TokenMint solanago.PublicKey `json:"tokenMint"` + Creator solanago.PublicKey `json:"creator"` + Base solanago.PublicKey `json:"base"` + EscrowBump uint8 `json:"escrowBump"` + UpdateRecipientMode uint8 `json:"updateRecipientMode"` + CancelMode uint8 `json:"cancelMode"` + TokenProgramFlag uint8 `json:"tokenProgramFlag"` + Padding0 [4]uint8 `json:"padding0"` + CliffTime uint64 `json:"cliffTime"` + Frequency uint64 `json:"frequency"` + CliffUnlockAmount uint64 `json:"cliffUnlockAmount"` + AmountPerPeriod uint64 `json:"amountPerPeriod"` + NumberOfPeriod uint64 `json:"numberOfPeriod"` + TotalClaimedAmount uint64 `json:"totalClaimedAmount"` + VestingStartTime uint64 `json:"vestingStartTime"` + CancelledAt uint64 `json:"cancelledAt"` + Padding1 uint64 `json:"padding1"` + Buffer [5]binary.Uint128 `json:"buffer"` +} + +type VestingEscrowMetadata struct { + Escrow solanago.PublicKey `json:"escrow"` + Name string `json:"name"` + Description string `json:"description"` + CreatorEmail string `json:"creatorEmail"` + RecipientEmail string `json:"recipientEmail"` +} + diff --git a/sql/01_schema.sql b/sql/01_schema.sql index 3f8b6770..d11bd131 100644 --- a/sql/01_schema.sql +++ b/sql/01_schema.sql @@ -3,8 +3,8 @@ -- --- Dumped from database version 17.6 (Debian 17.6-1.pgdg13+1) --- Dumped by pg_dump version 17.6 (Debian 17.6-1.pgdg13+1) +-- Dumped from database version 17.6 (Debian 17.6-2.pgdg13+1) +-- Dumped by pg_dump version 17.6 (Debian 17.6-2.pgdg13+1) SET statement_timeout = 0; SET lock_timeout = 0; @@ -7266,6 +7266,34 @@ CREATE TABLE public.sol_keypairs ( ); +-- +-- Name: sol_locker_vesting_escrows; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.sol_locker_vesting_escrows ( + account text NOT NULL, + slot bigint NOT NULL, + recipient text NOT NULL, + token_mint text NOT NULL, + creator text NOT NULL, + base text NOT NULL, + escrow_bump smallint NOT NULL, + update_recipient_mode smallint NOT NULL, + cancel_mode smallint NOT NULL, + token_program_flag smallint NOT NULL, + cliff_time bigint NOT NULL, + frequency bigint NOT NULL, + cliff_unlock_amount bigint NOT NULL, + amount_per_period bigint NOT NULL, + number_of_period bigint NOT NULL, + total_claimed_amount bigint NOT NULL, + vesting_start_time bigint NOT NULL, + cancelled_at bigint NOT NULL, + created_at timestamp without time zone DEFAULT now(), + updated_at timestamp without time zone DEFAULT now() +); + + -- -- Name: sol_meteora_damm_v2_pool_base_fees; Type: TABLE; Schema: public; Owner: - -- @@ -9483,6 +9511,14 @@ ALTER TABLE ONLY public.sol_keypairs ADD CONSTRAINT sol_keypairs_pkey PRIMARY KEY (public_key); +-- +-- Name: sol_locker_vesting_escrows sol_locker_vesting_escrows_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.sol_locker_vesting_escrows + ADD CONSTRAINT sol_locker_vesting_escrows_pkey PRIMARY KEY (account); + + -- -- Name: sol_meteora_damm_v2_pool_base_fees sol_meteora_damm_v2_pool_base_fees_pkey; Type: CONSTRAINT; Schema: public; Owner: - --