input-output-hk / nami

Nami Wallet is a browser based wallet extension to interact with the Cardano blockchain. Support requests: https://iohk.zendesk.com/hc/en-us/requests/new
https://namiwallet.io
Apache License 2.0
373 stars 167 forks source link

Get assets using injected api #47

Closed kraxyyy closed 2 years ago

kraxyyy commented 3 years ago

I can't find a way to retrieve all nfts of the wallet using the injected api, is there a way, and if, how?

Thanks

gerciljunio commented 3 years ago

I'm also looking for something similar, from what I've seen it's still not possible due to the injected API. But analyzing the nami source code, I noticed that they look in the blockfrost API and in blockfrost there is an endpoint where it returns the assets from a reward (stake) address.

I'm developing a platform in cardano which I need to return the NFTs inside nami, I'll probably have to use the blockfrost API, or maybe, I just don't understand correctly the injected nami API!

but it's a good question to your @kraxyyy \o/

alessandrokonrad commented 3 years ago

Hey you can call cardano.getBalance(), which returns a Value type, which is a cbor encoded hex string. To deserialize it you can use the serialization-lib. It's kinda low level at the moment, we will build a top-level API later on.

rooooooooob commented 3 years ago

@alessandrokonrad what do you have planned for the structure of the top level API? Will it be compatible with other wallets? (e.g. an intermediate layer between the dApp and CIP-30 externally available and part of the dApp not the wallet or something like that) Or how will this be handled? I've noticed in other issues there were users who wanted a very simple API too for handling only the simple cases like in #43

Saifadin commented 3 years ago

@alessandrokonrad what do you have planned for the structure of the top level API? Will it be compatible with other wallets? (e.g. an intermediate layer between the dApp and CIP-30 externally available and part of the dApp not the wallet or something like that) Or how will this be handled? I've noticed in other issues there were users who wanted a very simple API too for handling only the simple cases like in #43

As far as I know what @alessandrokonrad is doing is correct. The CIP30 defines the response of getBalance to be a cbor encoded hex string. So he would need to do it differently, which is unfortunately not gonna be compatible with other wallets. Let's see what changes to the CIP30 might come and what @alessandrokonrad will come up with

olliejm commented 2 years ago

Is anyone able to provide more specific info on how to deserialize the result of cardano.getBalance() via serialization-lib? I've not really been able to figure it out from any documentation or examples I can find

rooooooooob commented 2 years ago

I believe this should work @olliejm although I haven't tested it.

let rawBalance = await cardano.getBalance();
let balance = SerLib.Value.from_bytes(Buffer.from(rawBalance, 'hex'));
olliejm commented 2 years ago

Thanks, that gets me a little further, I know get an object with a value ptr, { ptr: XXX } where XXX is some number (that doesn't immediately appear to be my balance in either ADA or lovelace). I'm specifically wanting to get a list of assets in the wallet though, as the original issue was asking. I'm starting to think it's unlikely whatever value ptr is contains any information about assets, so maybe just using blockfrost is simpler

rooooooooob commented 2 years ago

That's how rust wasm-bindgen works. It's a handle to wasm linear memory. You can call methods on that according to what's in Value in the ser lib. If you're just looking for the ADA-only value (not multiassets/nfts) you can do balance.coin().to_str() to get the ADA-only value as a js string.

rooooooooob commented 2 years ago

@olliejm

I'm specifically wanting to get a list of assets in the wallet though

Ah sorry, try something like (untested):

let allAssets = balance.multiasset();
let assetTypes = allAssets.keys();
for (var i = 0; i < assetTypes.len(); i++) {
    let policyId = assetTypes.get(i);
    let assets = allAssets.get(polciyId);
    let assetNames = assets.keys();
    for (var j = 0; j < assetNames.len(); j++) {
        let assetName = assetNames.get(j);
        let asset = assets.get(assetName);
        let policyHex = Buffer.from(policyId.to_bytes()).toString('hex');
        let assetHex = Buffer.from(assetName.name()).toString('hex');
        console.log(`${policyHex}:${assetHex} = ${asset.to_str()}`);
    }
}

I'm just writing it in the comment box so maybe it's not entirely correct

olliejm commented 2 years ago

That makes sense now obviously about ptr, I forgot for a second this was WASM.

Your snippet above got me most of the way so thanks so much already. One issue was I had to get the key for the asset before getting the asset, e.g.

const allAssets = balance.multiasset();
const assetTypes = allAssets.keys();

for (let i = 0; i < assetTypes.len(); i++) {
  const policyId = assetTypes.get(i);
  const assets = allAssets.get(policyId);

  for (let j = 0; j < assets.len(); j++) {
    const name = assets.keys().get(j);
    const asset = assets.get(name).to_str();
    console.log(asset);
  }
}

I now have result logged to console, just a string "1". I have 1 asset from a single policy ID in my wallet, so I assume that's my balance of that specific asset.

What I need is the policy ID as a string (to filter out assets I'm not interested in), and the name of the asset (to fetch information about it from an external API).

I see policyId and name are already there now, but according to TypeScript no to_str method is available on them. If you're able to help any further it's massively appreciated, I will keep trial and erroring with the methods I can find in the lib

rooooooooob commented 2 years ago

Yeah I noticed after posting. I updated the comment. Check it out - it will give you the policy id and asset name as hex strings for both.

olliejm commented 2 years ago

That's perfect, everything I need now and without needing to call blockfrost. Thank you so much for the help, really appreciate it