uuosio / ascdk

MIT License
12 stars 9 forks source link

Selective notifications #25

Closed jafri closed 2 years ago

jafri commented 2 years ago

I need a way to implement the following pattern

    [[eosio::on_notify("*::transfer")]]
    void ontransfer_token (
      const name& from,
      const name& to,
      const asset& quantity,
      const string& memo
    );

    [[eosio::on_notify("atomicassets::transfer")]]
    void ontransfer_nfts (
      const name& from,
      const name& to,
      const vector<uint64_t>& asset_ids,
      const string& memo
    );

I saw the notify=true, but I think we need it to be selective to discern actions called, and cover * vs exact contract

learnforpractice commented 2 years ago

I think there is already an example:

https://github.com/uuosio/ascdk/blob/89988d2ecca9ba97f8dac3497b5e6c89844c90e0/examples/notify/receiver.ts#L11

learnforpractice commented 2 years ago

Ok, It's more complicated than I think. Give me a moment to write a demo for you.

learnforpractice commented 2 years ago

Here is the code. It can be compiled, but I have not tested it. Tell me if it does not work.

import {
    print,
    Contract,
    action,
    contract,
    Name,
    readActionData,
} from "as-chain";

@packer
class Transfer {
    from!: Name
    to!: Name
    quantity!: Name
    memo!: string
}

@packer
class NFTTransfer {
    from!: Name
    to!: Name
    asset_ids!: u64[]
    memo!: string
}

@contract("hello")
class MyContract extends Contract {
    @action("transfer", notify=true)
    transfer(): void {
        let data = readActionData()
        if (this.receiver == Name.fromString("atomicassets")) {
            let t = new NFTTransfer()
            t.unpack(data)
            print(`${t.from} ${t.to} ${t.asset_ids}`)
        } else {
            let t = new Transfer()
            t.unpack(data)
            print(`${t.from} ${t.to} ${t.quantity}`)
        }
    }
}
jafri commented 2 years ago

@learnforpractice I am getting

ERROR TS2339: Property 'from' does not exist on type '~lib/array/Array<u8>'.

    let data = readActionData()
    let t = new NFTTransfer()
    t.unpack(data)
    if (data.from == this.receiver) {
learnforpractice commented 2 years ago
if (t.from == this.receiver) {
jafri commented 2 years ago

Cool that works, just ugly warning from typescript

Screen Shot 2022-03-06 at 10 07 02 PM
learnforpractice commented 2 years ago

Yeah, the following code is much prettier. See 093fb8265b39002772eed7efe8b9471e442ff258

import {
    unpackActionData,
} from "as-chain";

let t = unpackActionData<NFTTransfer>()
if (t.from == this.receiver) {
jafri commented 2 years ago

@learnforpractice last error here:

Screen Shot 2022-03-06 at 10 45 18 PM

Can we change @action("transfer", notify=true) to @action("transfer", { notify: true })

learnforpractice commented 2 years ago

I think we need to keep the implementation simple enough.

jafri commented 2 years ago

@learnforpractice how about just @action("transfer", true) then? We should aim to eliminate all errors in type-checking

learnforpractice commented 2 years ago

Well, that reduces the readability. But for the reason of eliminating type-checking errors, I agree with the change.

jafri commented 2 years ago

Would you rather true or { notify: true }?

learnforpractice commented 2 years ago

{ notify: true } in a decorator is kind of wired. true is fine I think.

jafri commented 2 years ago

@learnforpractice actually I saw something you did elsewhere with singleton,

lets do @action("transfer", notify)

learnforpractice commented 2 years ago

Yeah, that's better.

learnforpractice commented 2 years ago

Solved by e6eb2bd8db0803a597aed24f7d0ccf596490526a