scrtlabs / snip20-reference-impl

This is a reference implementation of the SNIP-20 standard.
Apache License 2.0
55 stars 36 forks source link

SNIP-24 - Query Permits #22

Closed assafmo closed 3 years ago

assafmo commented 3 years ago

A way to do authenticated queries without needing to set a viewing key first. :eyes:

Docs: https://github.com/SecretFoundation/SNIPs/blob/master/SNIP-24.md

Keplr example (SNIP-20):

const permitName = "secretswap.io";
const allowedTokens = ["secret18vd8fpwxzck93qlwghaj6arh4p7c5n8978vsyg"];
const permissions = ["balance" /* , "history", "allowance" */];

const { signature } = await window.keplr.signAmino(
  chainId,
  myAddress,
  {
    chain_id: chainId,
    account_number: "0", // Must be 0
    sequence: "0", // Must be 0
    fee: {
      amount: [{ denom: "uscrt", amount: "0" }], // Must be 0 uscrt
      gas: "1", // Must be 1
    },
    msgs: [
      {
        type: "query_permit", // Must be "query_permit"
        value: {
          permit_name: permitName,
          allowed_tokens: allowedTokens,
          permissions: permissions,
        },
      },
    ],
    memo: "", // Must be empty
  },
  {
    preferNoSetFee: true, // Fee must be 0, so hide it from the user
    preferNoSetMemo: true, // Memo must be empty, so hide it from the user
  }
);

const { balance } = await secretjs.queryContractSmart(
  "secret18vd8fpwxzck93qlwghaj6arh4p7c5n8978vsyg",
  {
    with_permit: {
      query: { balance: {} },
      permit: {
        params: {
          permit_name: permitName,
          allowed_tokens: allowedTokens,
          chain_id: chainId,
          permissions: permissions,
        },
        signature: signature,
      },
    },
  }
);

console.log(balance.amount);

Keplr example (SNIP-721):

const permitName = "A cool Secret NFT game";
const allowedTokens = ["secret18vd8fpwxzck93qlwghaj6arh4p7c5n8978vsyg"];
const permissions = ["owner"];

const { signature } = await window.keplr.signAmino(
  chainId,
  myAddress,
  {
    chain_id: chainId,
    account_number: "0", // Must be 0
    sequence: "0", // Must be 0
    fee: {
      amount: [{ denom: "uscrt", amount: "0" }], // Must be 0 uscrt
      gas: "1", // Must be 1
    },
    msgs: [
      {
        type: "query_permit", // Must be "query_permit"
        value: {
          permit_name: permitName,
          allowed_tokens: allowedTokens,
          permissions: permissions,
        },
      },
    ],
    memo: "", // Must be empty
  },
  {
    preferNoSetFee: true, // Fee must be 0, so hide it from the user
    preferNoSetMemo: true, // Memo must be empty, so hide it from the user
  }
);

const tokens = await secretjs.queryContractSmart(
  "secret18vd8fpwxzck93qlwghaj6arh4p7c5n8978vsyg",
  {
    with_permit: {
      query: { tokens: {} },
      permit: {
        params: {
          permit_name: permitName,
          allowed_tokens: allowedTokens,
          chain_id: chainId,
          permissions: permissions,
        },
        signature: signature,
      },
    },
  }
);

console.log(tokens);

CLI example (SNIP-20):

$ echo '{
    "chain_id": "secret-3",
    "account_number": "0",
    "sequence": "0",
    "msgs": [
        {
            "type": "query_permit",
            "value": {
                "permit_name": "test",
                "allowed_tokens": [
                    "secret18vd8fpwxzck93qlwghaj6arh4p7c5n8978vsyg"
                ],
                "permissions": ["balance"]
            }
        }
    ],
    "fee": {
        "amount": [
            {
                "denom": "uscrt",
                "amount": "0"
            }
        ],
        "gas": "1"
    },
    "memo": ""
}' > ./permit.json
$ secretcli tx sign-doc ./permit.json --from yo > ./sig.json
$ secretcli q compute query secret18vd8fpwxzck93qlwghaj6arh4p7c5n8978vsyg '{"with_permit":{"query":{"balance":{}},"permit":{"params":{"permit_name":"test","allowed_tokens":["secret18vd8fpwxzck93qlwghaj6arh4p7c5n8978vsyg"],"chain_id":"secret-3","permissions":["balance"]},"signature":'"$(cat ./sig.json)"'}}}'
assafmo commented 3 years ago

https://github.com/enigmampc/QueryBalancePermitDemo

the-dusky commented 3 years ago

Does this mean that you will need to sign a tx every time you query a balance? Will this live along side viewing keys as a sort of "one time passcode" for queries that access private state?

assafmo commented 3 years ago

@the-dusky

Does this mean that you will need to sign a tx every time you query a balance?

No, you sign it offline (you don't broadcast a tx) and the signature (=permit) is sent with the balance query (like a viewing key) and is reusable for multiple queries. To revoke a permit the user needs to send a "revoke permit" tx.

Will this live along side viewing keys as a sort of "one time passcode" for queries that access private state?

This is an addition, so viewing keys remain untouched. It's reusable, so not exactly a "one time passcode".

dylanschultzie commented 3 years ago

Omg it's happening. 😍