我想获得所有给定地址的交易

I would like to get all transactions given an address

给定一个 Solana 钱包地址,我想验证曾经确认过的每一笔交易,以检查其他信息,例如接收方(或发送方)和发送(或接收)的金额。所以,像往常一样,我搜索了一些 API。我发现了以下内容:

  1. Solana py
  2. PySolana

之后我就去看看他们有哪些方法。 solana_client.get_confirmed_signature_for_address2(在 1 中可用)似乎接近我的期望,但我的结果与其文档显示的不符。在这里:

from solana.rpc.api import Client
solana_client = Client("https://api.devnet.solana.com")

solana_client.get_signatures_for_address("2AQdpHJ2JpcEgPiATUXjQxA8QmafFegfQwSLWSprPicm", limit=1)

我明白了:

{'jsonrpc': '2.0', 'result': [], 'id': 1}

不过,我应该得到它的最后一个签名,好像是这样的:

4SNQ4h1vL9GkmSnojQsf8SZyFvQsaq62RCgops2UXFYag1Jc4MoWrjTg2ELwMqM1tQbn9qUcNc4tqX19EGHBqC5u

无论如何,我们可以使用 SolanaBeach 和 check。此外,如果我们按照文档说明进行编码:

from solana.rpc.api import Client
solana_client = Client("https://api.devnet.solana.com")

solana_client.get_signatures_for_address("Vote111111111111111111111111111111111111111", limit=1)

我明白了:

{'jsonrpc': '2.0', 'result': [{'blockTime': 1637328065, 'confirmationStatus': 'finalized', 'err': {'InstructionError': [0, {'Custom': 0}]}, 'memo': None, 'signature': '5yaeqDRCHWCGQMqNWhq3g6zqw63MBkri9i86hjK954YFFvnG2VCQJfszXsozDVUJbePagJieAzwsSY5H7Xd1jJhC', 'slot': 95301596}], 'id': 1}

奇怪的是“Vote111...11”似乎不是地址。然而,我得到了预期的结果,这是一个签名,即使这样的签名不能被 Solana Explorer 找到...

请告诉我要解决的问题。我不知道该怎么做。我什至试图检查是否所有 Solana Explorer 都有自己的 API,但他们没有。可能是因为 Solana 已经分享了它,对吧?

编辑

嗯,看来我需要输入“账户地址为base-58编码的字符串”,因此地址变成:HLiBGYYxaQqQx8UTPHEahqcd7aZjkDgN3bihc3hYM3SDUBGU9LFrQSnx9eje。

我也这样做了,我得到:

{'jsonrpc': '2.0', 'error': {'code': -32602, 'message': 'Invalid param: WrongSize'}, 'id': 1}

我已经实现了获取给定地址在 javaScript 上的所有交易的功能,这可能会对您有所帮助。

    async getTransactionsOfUser(address, options, connection) {
    console.log({ address, options });
    try {
      const publicKey = new PublicKey(address);
      const transSignatures =
        await connection.getConfirmedSignaturesForAddress2(publicKey, options);
      console.log({ transSignatures });
      const transactions = [];
      for (let i = 0; i < transSignatures.length; i++) {
        const signature = transSignatures[i].signature;
        const confirmedTransaction = await connection.getConfirmedTransaction(
          signature,
        );
        if (confirmedTransaction) {
          const { meta } = confirmedTransaction;
          if (meta) {
            const oldBalance = meta.preBalances;
            const newBalance = meta.postBalances;
            const amount = oldBalance[0] - newBalance[0];
            const transWithSignature = {
              signature,
              ...confirmedTransaction,
              fees: meta?.fee,
              amount,
            };
            transactions.push(transWithSignature);
          }
        }
      }
      return transactions;
    } catch (err) {
      throw err;
    }
  }

问题不是 module 也不是 function,而是 endpoint

Solana Doc 中我发现 endpoint mainnet:

https://api.mainnet-beta.solana.com

https://solana-api.projectserum.com

它给出了所有值。


other page 你可以看到

  • devnet 仅用于测试 playgroundtokens are not real
  • testnet 仅适用于 stress testtokens are not real
#Devnet#

- Devnet serves as a playground for anyone who wants to take Solana for a test drive, as a user, token holder, app developer, or validator.
- Application developers should target Devnet.
- Potential validators should first target Devnet.
- Key differences between Devnet and Mainnet Beta:
    - Devnet tokens are not real
    - Devnet includes a token faucet for airdrops for application testing
    - Devnet may be subject to ledger resets
    - Devnet typically runs a newer software version than Mainnet Beta

#Testnet#

-Testnet is where we stress test recent release features on a live cluster, particularly focused on network performance, stability and validator behavior.
- Testnet tokens are not real
- Testnet may be subject to ledger resets.
- Testnet includes a token faucet for airdrops for application testing
- Testnet typically runs a newer software release than both Devnet and Mainnet Beta

测试的最小工作示例:

from solana.rpc.api import Client

all_addresses = [
    '2AQdpHJ2JpcEgPiATUXjQxA8QmafFegfQwSLWSprPicm',
    'Vote111111111111111111111111111111111111111',
    'fake address',
]

#endpoint = 'https://api.devnet.solana.com'    # probably for `developing`
#endpoint = 'https://api.testnet.solana.com'   # probably for `testing`
endpoint = 'https://api.mainnet-beta.solana.com'
#endpoint = 'https://solana-api.projectserum.com'

solana_client = Client(endpoint)

for address in all_addresses:
    print('address:', address)
    
    #result = solana_client.get_confirmed_signature_for_address2(address, limit=1)
    result = solana_client.get_signatures_for_address(address)#, before='89Tv9s2uMGaoxB8ZF1LV9nGa72GQ9RbkeyCDvfPviWesZ6ajZBFeHsTPfgwjGEnH7mpZa7jQBXAqjAfMrPirHt2')
    
    if 'result' in result:
        print('len:', len(result['result']))

        # I use `[:5]` to display only first 5 values
        for number, item in enumerate(result['result'][:5], 1):
            print(number, 'signature:', item['signature'])

        # check if there is `4SNQ4h1vL9GkmSnojQsf8SZyFvQsaq62RCgops2UXFYag1Jc4MoWrjTg2ELwMqM1tQbn9qUcNc4tqX19EGHBqC5u`
        for number, item in enumerate(result['result'], 1):
            if item['signature'].startswith('4SN'):
                print('found at', number, '>>>', item['signature'])

    else:
        # error message 
        print(result)

    print('---')

    #solana_client.get_account_info(address)

结果:

address: 2AQdpHJ2JpcEgPiATUXjQxA8QmafFegfQwSLWSprPicm
len: 1000
1 signature: 89Tv9s2uMGaoxB8ZF1LV9nGa72GQ9RbkeyCDvfPviWesZ6ajZBFeHsTPfgwjGEnH7mpZa7jQBXAqjAfMrPirHt2
2 signature: 3Ku2rDnAVo5Mj3r9CVSGHJjvn4H9rxzDvc5Cg5uyeCC9oa6p7enAG88pSfRfxcqhBh2JiWSo7ZFEAD3mP8teS1Yg
3 signature: 3wiYCmfXb9n6pT3mgBag7jx6jBjeKZowkYmeakMibw4GtERFyyitrmmoPU6t28HpJJgWkArymWEGWQj8eiojswoD
4 signature: 5vjV1wKU3ZEgyzqXCKrJcJx5jGC8LPqRiJBwhPcu62HQU64mkrvkK8LKYaTzX4x4p26UXSufWM57zKSxRrMgjWn3
5 signature: 3aLk4xZPcWRogtvsFe8geYC177PK8s47mgqUErteRc9NJ4EF2iHi3GPsaj5guTwyiabhwivFhrrEk4YQgiE2hZs8
found at 970 >>> 4SNQ4h1vL9GkmSnojQsf8SZyFvQsaq62RCgops2UXFYag1Jc4MoWrjTg2ELwMqM1tQbn9qUcNc4tqX19EGHBqC5u
---
address: Vote111111111111111111111111111111111111111
len: 1000
1 signature: 67RRbUWGCrwmJ3hhLL7aB2K8gc6MewxwgAdfG7FeXQBaSstacqvuo9QUPZ6nhqXjJwYpKHihNJwFfcaAZHuyFmMc
2 signature: 67PsyRRw8bXgtsB49htxcW2FE9cyyBrocUKacnrxJpqaBpFT6QDLrCkyovWnM8XyGKxTv3kqzmW72SH7gj3N8YJr
3 signature: 675FWqrAjE5Bt6rf3KD2H2PCKUmEtrcD8BRRypdS7m2V22zXhrGn3SktP6JYW4ws6xEqDj52MZMH8RwNjoqgW4mt
4 signature: 671K7N9FwaMAyBC4MEYbYb1ACYAendBbRMqKPvr3h63dt5ybAPHyppjHwxq1yPDjqaRUwCBVU9o5dVqgsdVabint
5 signature: 666jBXXLwmB5tuvufhNn8Q7A3eCzGo6CBFD5BYJkuGfBf1bRoAGz4DeEpUAKsUrRk4NdRBhYkwfrhyZjgFmo3Dp2
---
address: fake address
{'jsonrpc': '2.0', 'error': {'code': -32602, 'message': 'Invalid param: Invalid'}, 'id': 3}
---

顺便说一句:

因为它只得到 1000 个值,所以你现在可能看不到位于 ~1200 位置的 4SNQ...,但是如果你使用 before=

get_signatures_for_address(address, before='89Tv9s2uMGaoxB8ZF1LV9nGa72GQ9RbkeyCDvfPviWesZ6ajZBFeHsTPfgwjGEnH7mpZa7jQBXAqjAfMrPirHt2')

那么它应该在~970的位置


顺便说一句:

Solana Explorer 上,您有一个大按钮可以将 Mainnet 更改为 Devnet,当您使用 Devnet 时,则 2AQdpHJ2JpcEgPiATUXjQxA8QmafFegfQwSLWSprPicm 也给出了 0 个项目。

Solana Beach 也一样。还有一个大按钮可以将 Mainnet 更改为 Devnet 并且当您使用 Devnet2AQdpHJ2JpcEgPiATUXjQxA8QmafFegfQwSLWSprPicm 给出 0 个项目。

有趣的是,今天早上我正在处理这个完全相同的问题。就像 furas 指出的那样,它是端点,需要使用主网端点:

https://api.mainnet-beta.solana.com

虽然文档说您需要输入 base-58 地址,但我发现它有点令人困惑,我尝试了与您相同的方法,但它给了我同样的错误,结果我只需要直接复制粘贴我的地址