Skip to content

Instantly share code, notes, and snippets.

@csknk
Last active November 11, 2021 14:31
Show Gist options
  • Save csknk/2e42fe992b43d2d9ddc418b3f336e2b3 to your computer and use it in GitHub Desktop.
Save csknk/2e42fe992b43d2d9ddc418b3f336e2b3 to your computer and use it in GitHub Desktop.

Revisions

  1. csknk revised this gist Nov 11, 2021. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions extrinsic_test.go
    Original file line number Diff line number Diff line change
    @@ -51,10 +51,9 @@ func DecodeExtrinsic(t *testing.T, c *Connection, extrinsicString string) error
    }
    fmt.Println("CALLS # ", n)

    // TODO Maybe loop over n - can there be multiple calls?
    // TODO Maybe loop over n
    // Probably should get the metadata for the specific block that contains this extrinsic?
    metadata, _ := c.getLatestMetadata()
    // fmt.Printf("%#x\n", decodedExtrinsic.Signature.Signer.AsID)

    callFunction := findModule(metadata, decodedExtrinsic.Method.CallIndex)

    for _, callArg := range callFunction.Args {
    @@ -74,6 +73,7 @@ func DecodeExtrinsic(t *testing.T, c *Connection, extrinsicString string) error
    fmt.Println(callArg.Name, " = ", argValue)
    }
    }

    return nil
    }

  2. csknk created this gist Nov 11, 2021.
    88 changes: 88 additions & 0 deletions extrinsic_test.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,88 @@
    package main

    import (
    "bytes"
    "fmt"
    "math/big"
    "testing"

    "github.com/centrifuge/go-substrate-rpc-client/v3/scale"
    "github.com/centrifuge/go-substrate-rpc-client/v3/types"
    "github.com/stretchr/testify/assert"
    )

    func TestEncodeDecodeExtrinsic(t *testing.T) {
    c, err := NewDefaultConnection()
    if err != nil {
    fmt.Println("No connection to node")
    assert.Fail(t, err.Error())
    }
    AlicePubkey := "0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d" // 15oF4uVJwmo4TdGW7VfQxNLavjCXviqxT9S1MgbjMNHr6Sp5
    BobPubkey := "0x8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48" // 14E5nqKAp3oAJcmzgZhUD2RcptBeUBScxKHgJKU4HPNcKVf3
    var amount uint64 = 4200000000

    extrinsic, err := c.NewExtrinsic(AlicePubkey, BobPubkey, amount)
    assert.NoError(t, err)

    extrinsicString, err := types.EncodeToHexString(extrinsic)
    if err != nil {
    assert.NoError(t, err)
    }
    fmt.Println("Signed extrinsic: ", extrinsicString)

    _ = DecodeExtrinsic(t, c, extrinsicString)

    }

    func DecodeExtrinsic(t *testing.T, c *Connection, extrinsicString string) error {
    var decodedExtrinsic types.Extrinsic
    if err := types.DecodeFromHexString(extrinsicString, &decodedExtrinsic); err != nil {
    assert.Fail(t, err.Error())
    }
    fmt.Printf("%+v\n", decodedExtrinsic.Method.Args)

    decoder := scale.NewDecoder(bytes.NewReader(decodedExtrinsic.Method.Args))

    // Determine number of calls
    // NOTE IT IS NECESSARY TO REMOVE BYTE FROM STREAM - otherwise subsequent decoding won't work properly.
    n, err := decoder.DecodeUintCompact()
    if err != nil {
    assert.Fail(t, err.Error())
    }
    fmt.Println("CALLS # ", n)

    // TODO Maybe loop over n - can there be multiple calls?
    metadata, _ := c.getLatestMetadata()
    // fmt.Printf("%#x\n", decodedExtrinsic.Signature.Signer.AsID)

    callFunction := findModule(metadata, decodedExtrinsic.Method.CallIndex)

    for _, callArg := range callFunction.Args {
    if callArg.Type == "<T::Lookup as StaticLookup>::Source" {
    var argValue = types.AccountID{}
    decoder.Decode(&argValue)
    fmt.Println(callArg.Name, " = ", argValue)
    fmt.Printf("%#x\n", argValue)
    }
    if callArg.Type == "Compact<T::Balance>" {
    amount, _ := decoder.DecodeUintCompact()
    fmt.Println(callArg.Name, " = ", amount)
    }
    if callArg.Type == "Vec<u8>" {
    var argValue = callArg.Name
    _ = decoder.Decode(&argValue)
    fmt.Println(callArg.Name, " = ", argValue)
    }
    }
    return nil
    }

    func findModule(metadata *types.Metadata, index types.CallIndex) types.FunctionMetadataV4 {
    for _, mod := range metadata.AsMetadataV13.Modules {
    if mod.Index == index.SectionIndex {
    return mod.Calls[index.MethodIndex]
    }
    }
    panic("Unknown call")
    }