michaelhly / solana-py

Solana Python SDK
https://michaelhly.github.io/solana-py
MIT License
981 stars 252 forks source link

Can't append to Instruction Accounts #353

Closed Bewinxed closed 1 year ago

Bewinxed commented 1 year ago

In the previous versions, I used to be able to create a TransferChecked instruction and then append an account to it, for SolanaPay, I need to add a reference account (pubkey) to the list of accounts in the tx.

However, appending to the instruction.accounts now does nothing, the list stays the same.

assigning to the list like instruction.accounts = instruction.accounts + [AccountMeta(reference, False, False)] appends the list but the instruction still doesn't include that account in the list.

How to go about that? I'm just making a transaction checked but i need to include the account in the transaction somehow.

Thanks!

michaelhly commented 1 year ago

@Bewinxed could you provide a code snippet?

Bewinxed commented 1 year ago

LAMPORTS_PER_SOL = Decimal("1000000000")

transactionAmount = int(
                (
                    amount * LAMPORTS_PER_SOL * Decimal(1 - feePercentage)
                ).to_integral_value("ROUND_FLOOR")
            )
transactionInstruction = transfer(
                TransferParams(from_pubkey=payer, to_pubkey= recipient, lamports= transactionAmount)
            )
feeAmount = int(
                (
                    amount * LAMPORTS_PER_SOL * Decimal(feePercentage)
                ).to_integral_value("ROUND_FLOOR")
            )
feeInstruction = transfer(
                TransferParams(from_pubkey=payer, to_pubkey= feeRecipient, lamports= feeAmount)
            )
transactionInstruction.accounts = transactionInstruction.accounts + [AccountMeta(reference, False, False)] # <-- this used to work
transaction.add(transactionInstruction, feeInstruction)

I used to be able to include the AccountMeta(reference, False, False) in the transfer instruction.

michaelhly commented 1 year ago

it got moved over here: https://kevinheavey.github.io/solders/api_reference/instruction.html#solders.instruction.Instruction

Bewinxed commented 1 year ago

So we can't use transfer checked and add to the result of it? Gotta build it manually?

On Sun, 7 May 2023 at 6:48 AM Michael Huang @.***> wrote:

it got moved over here:

https://kevinheavey.github.io/solders/api_reference/instruction.html#solders.instruction.Instruction

— Reply to this email directly, view it on GitHub https://github.com/michaelhly/solana-py/issues/353#issuecomment-1537281479, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACFY5BO6UMWADYFT7HV6IHDXE4LRLANCNFSM6AAAAAAXYR5AMI . You are receiving this because you were mentioned.Message ID: @.***>

michaelhly commented 1 year ago

cc @kevinheavey, is there a method in solders where we can append to account meta? If not where would be an appropriate place to add one?

kevinheavey commented 1 year ago

I'd recommend just building it manually. We could add mutability to the solders Instruction but that would introduce a major footgun: https://pyo3.rs/main/faq#pyo3get-clones-my-field

Safer to have one grug-brained way to do it imo

Bewinxed commented 1 year ago

So how would I build a transfer_checked transaction using this?

Trying to wrap my head around the new changes.

Thanks!

On Sun, May 7, 2023 at 2:59 PM Kevin Heavey @.***> wrote:

I'd recommend just building it manually. We could add mutability to the solders Instruction but that would introduce a major footgun: https://pyo3.rs/main/faq#pyo3get-clones-my-field

Safer to have one grug-brained way to do it imo

— Reply to this email directly, view it on GitHub https://github.com/michaelhly/solana-py/issues/353#issuecomment-1537422546, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACFY5BLLDCNKZWAKKZUNZQLXE6FCRANCNFSM6AAAAAAXYR5AMI . You are receiving this because you were mentioned.Message ID: @.***>

kevinheavey commented 1 year ago

Something like this:

LAMPORTS_PER_SOL = Decimal("1000000000")

transactionAmount = int(
                (
                    amount * LAMPORTS_PER_SOL * Decimal(1 - feePercentage)
                ).to_integral_value("ROUND_FLOOR")
            )
base_ix = transfer(
                TransferParams(from_pubkey=payer, to_pubkey= recipient, lamports= transactionAmount)
            )
feeAmount = int(
                (
                    amount * LAMPORTS_PER_SOL * Decimal(feePercentage)
                ).to_integral_value("ROUND_FLOOR")
            )
feeInstruction = transfer(
                TransferParams(from_pubkey=payer, to_pubkey= feeRecipient, lamports= feeAmount)
            )
transaction_instruction = Instruction(base_ix.program_id, base_ix.data, base_ix.accounts  + [AccountMeta(reference, False, False)])
Bewinxed commented 1 year ago

Works great, thank you!

On Sun, 7 May 2023 at 3:14 PM Kevin Heavey @.***> wrote:

Something like this:

LAMPORTS_PER_SOL = Decimal("1000000000")

transactionAmount = int( ( amount LAMPORTS_PER_SOL Decimal(1 - feePercentage) ).to_integral_value("ROUND_FLOOR") ) base_ix = transfer( TransferParams(from_pubkey=payer, to_pubkey= recipient, lamports= transactionAmount) ) feeAmount = int( ( amount LAMPORTS_PER_SOL Decimal(feePercentage) ).to_integral_value("ROUND_FLOOR") ) feeInstruction = transfer( TransferParams(from_pubkey=payer, to_pubkey= feeRecipient, lamports= feeAmount) ) transaction_instruction = Instruction(base_ix.program_id, base_ix.data, base_ix.accounts + [AccountMeta(reference, False, False)])

— Reply to this email directly, view it on GitHub https://github.com/michaelhly/solana-py/issues/353#issuecomment-1537426475, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACFY5BK7VRGBFQICDNIHWXTXE6G3RANCNFSM6AAAAAAXYR5AMI . You are receiving this because you were mentioned.Message ID: @.***>

kevinheavey commented 1 year ago

@Bewinxed I forgot that solders actually is supposed to support overwriting the accounts field.

It even has a passing test for this behaviour:

@fixture
def ix() -> Instruction:
    return Instruction(
        Pubkey.default(), b"1", [AccountMeta(Pubkey.new_unique(), True, True)]
    )

@fixture
def am() -> AccountMeta:
    return AccountMeta(Pubkey.new_unique(), True, True)

def test_accounts_setter(ix: Instruction, am: AccountMeta) -> None:
    new_accounts = [am]
    ix.accounts = new_accounts
    assert ix.accounts == new_accounts

What behaviour exactly are you seeing here?

assigning to the list like instruction.accounts = instruction.accounts + [AccountMeta(reference, False, False)] appends the list but the instruction still doesn't include that account in the list.

Bewinxed commented 1 year ago

If you do tx.accounts.append(account), then account doesn't get appended to the list at all.

if you do tx.accounts = tx.accounts + [account] the list gets appended, however if you try to send the transaction, that account isn't included at all in the transaction.

On Wed, May 10, 2023 at 11:07 AM Kevin Heavey @.***> wrote:

@Bewinxed https://github.com/Bewinxed I forgot that solders actually is supposed to support overwriting the accounts field.

It even has a passing test for this behaviour:

@fixture def ix() -> Instruction: return Instruction( Pubkey.default(), b"1", [AccountMeta(Pubkey.new_unique(), True, True)] )

@fixture def am() -> AccountMeta: return AccountMeta(Pubkey.new_unique(), True, True)

def test_accounts_setter(ix: Instruction, am: AccountMeta) -> None: new_accounts = [am] ix.accounts = new_accounts assert ix.accounts == new_accounts

What behaviour exactly are you seeing here?

assigning to the list like instruction.accounts = instruction.accounts + [AccountMeta(reference, False, False)] appends the list but the instruction still doesn't include that account in the list.

— Reply to this email directly, view it on GitHub https://github.com/michaelhly/solana-py/issues/353#issuecomment-1541540996, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACFY5BJXKTOTOA7L7LYYAXLXFNEFZANCNFSM6AAAAAAXYR5AMI . You are receiving this because you were mentioned.Message ID: @.***>