From 045fa4d6f38bb74c03349d92545a9006bdd02fd2 Mon Sep 17 00:00:00 2001 From: Marko Petrlic Date: Thu, 16 Jan 2025 11:52:46 +0100 Subject: [PATCH 1/3] Reimplementation v020 --- complex/block.go | 187 ++++ complex/block_transaction.go | 63 ++ complex/client.go | 158 +++ complex/events.go | 287 +++++ complex/rpc.go | 74 ++ complex/rpc_chain.go | 55 + complex/rpc_chain_spec.go | 15 + complex/rpc_state.go | 63 ++ complex/rpc_system.go | 33 + complex/transaction.go | 153 +++ complex/transaction_options.go | 57 + examples/README.md | 991 ------------------ examples/balance_allow_death/main.go | 34 - examples/balance_transfer_all/main.go | 28 - examples/balances_keep_alive/main.go | 34 - examples/config.json | 8 - examples/connect/main.go | 35 - examples/da_create_application_key/main.go | 29 - examples/da_data_submit/main.go | 36 - examples/da_data_submit_watch/main.go | 36 - examples/da_set_application_key/main.go | 30 - examples/da_submit_block_length/main.go | 30 - examples/da_submit_data_fee_modifier/main.go | 42 - examples/estimate-fee/main.go | 77 -- examples/existential/main.go | 20 - examples/go.mod | 34 - examples/go.sum | 87 -- examples/listenNewBlocks/main.go | 38 - examples/properties/main.go | 31 - examples/rpc/author_rotate/main.go | 29 - examples/rpc/chain_finalizedHead/main.go | 29 - examples/rpc/chain_getBlock/main.go | 29 - examples/rpc/chain_getBlockHash/main.go | 29 - examples/rpc/chain_getHeader/main.go | 29 - examples/rpc/kate_queryProof/main.go | 54 - examples/rpc/kate_queryProofData/main.go | 74 -- examples/rpc/kate_queryRows/main.go | 59 -- examples/staking_bond/main.go | 31 - examples/staking_bond_extra/main.go | 29 - examples/staking_chill/main.go | 27 - examples/staking_chill_other/main.go | 28 - examples/staking_nominate/main.go | 28 - examples/staking_unbond/main.go | 35 - examples/staking_validate/main.go | 28 - go.mod | 21 +- go.sum | 20 +- interfaces/mod.go | 16 + justfile | 11 + main.go | 80 ++ metadata/README.md | 6 + metadata/metadata.go | 354 +++++++ metadata/pallets/balances/calls.go | 194 ++++ metadata/pallets/balances/events.go | 49 + metadata/pallets/balances/mod.go | 4 + metadata/pallets/data_availability/calls.go | 96 ++ metadata/pallets/data_availability/events.go | 51 + metadata/pallets/data_availability/mod.go | 4 + metadata/pallets/mod.go | 1 + metadata/pallets/system/events.go | 47 + metadata/pallets/system/mod.go | 4 + .../pallets/transaction_payment/events.go | 30 + metadata/pallets/transaction_payment/mod.go | 4 + metadata/payload.go | 27 + metadata/types.go | 304 ++++++ primitives/address.go | 94 ++ primitives/already_encoded.go | 21 + primitives/block.go | 46 + primitives/extrinsics_decoded.go | 81 ++ primitives/extrinsics_encoded.go | 67 ++ primitives/extrinsics_payload.go | 160 +++ primitives/extrinsics_payload_test.go | 40 + primitives/extrinsics_sign.go | 27 + primitives/hash_h256.go | 38 + primitives/hash_h512.go | 38 + primitives/hash_h520.go | 38 + primitives/header.go | 52 + primitives/runtime_version.go | 64 ++ primitives/scale_decoder.go | 328 ++++++ primitives/scale_decoder_test.go | 312 ++++++ primitives/scale_encoder.go | 260 +++++ primitives/scale_encoder_test.go | 436 ++++++++ primitives/scale_hex.go | 17 + primitives/scale_types.go | 93 ++ primitives/signature.go | 85 ++ run_tests.sh | 2 + sdk.go | 51 + src/config/config.go | 59 -- src/extrinsic/era.go | 163 --- src/extrinsic/extrinsic.go | 262 ----- src/extrinsic/payload.go | 158 --- src/header/header.go | 74 -- src/rpc/block.go | 91 -- src/rpc/kate.go | 150 --- src/rpc/submit.go | 88 -- src/sdk/call/call.go | 55 - src/sdk/callExtrinsic.go | 208 ---- src/sdk/events.go | 525 ---------- src/sdk/helper.go | 359 ------- src/sdk/sdk.go | 32 - src/sdk/tx/transactions.go | 470 --------- src/sdk/types/types.go | 24 - src/sdk/types/ucompact.go | 54 - 102 files changed, 4795 insertions(+), 4953 deletions(-) create mode 100644 complex/block.go create mode 100644 complex/block_transaction.go create mode 100644 complex/client.go create mode 100644 complex/events.go create mode 100644 complex/rpc.go create mode 100644 complex/rpc_chain.go create mode 100644 complex/rpc_chain_spec.go create mode 100644 complex/rpc_state.go create mode 100644 complex/rpc_system.go create mode 100644 complex/transaction.go create mode 100644 complex/transaction_options.go delete mode 100644 examples/README.md delete mode 100644 examples/balance_allow_death/main.go delete mode 100644 examples/balance_transfer_all/main.go delete mode 100644 examples/balances_keep_alive/main.go delete mode 100644 examples/config.json delete mode 100644 examples/connect/main.go delete mode 100644 examples/da_create_application_key/main.go delete mode 100644 examples/da_data_submit/main.go delete mode 100644 examples/da_data_submit_watch/main.go delete mode 100644 examples/da_set_application_key/main.go delete mode 100644 examples/da_submit_block_length/main.go delete mode 100644 examples/da_submit_data_fee_modifier/main.go delete mode 100644 examples/estimate-fee/main.go delete mode 100644 examples/existential/main.go delete mode 100644 examples/go.mod delete mode 100644 examples/go.sum delete mode 100644 examples/listenNewBlocks/main.go delete mode 100644 examples/properties/main.go delete mode 100644 examples/rpc/author_rotate/main.go delete mode 100644 examples/rpc/chain_finalizedHead/main.go delete mode 100644 examples/rpc/chain_getBlock/main.go delete mode 100644 examples/rpc/chain_getBlockHash/main.go delete mode 100644 examples/rpc/chain_getHeader/main.go delete mode 100644 examples/rpc/kate_queryProof/main.go delete mode 100644 examples/rpc/kate_queryProofData/main.go delete mode 100644 examples/rpc/kate_queryRows/main.go delete mode 100644 examples/staking_bond/main.go delete mode 100644 examples/staking_bond_extra/main.go delete mode 100644 examples/staking_chill/main.go delete mode 100644 examples/staking_chill_other/main.go delete mode 100644 examples/staking_nominate/main.go delete mode 100644 examples/staking_unbond/main.go delete mode 100644 examples/staking_validate/main.go create mode 100644 interfaces/mod.go create mode 100644 justfile create mode 100644 main.go create mode 100644 metadata/README.md create mode 100644 metadata/metadata.go create mode 100644 metadata/pallets/balances/calls.go create mode 100644 metadata/pallets/balances/events.go create mode 100644 metadata/pallets/balances/mod.go create mode 100644 metadata/pallets/data_availability/calls.go create mode 100644 metadata/pallets/data_availability/events.go create mode 100644 metadata/pallets/data_availability/mod.go create mode 100644 metadata/pallets/mod.go create mode 100644 metadata/pallets/system/events.go create mode 100644 metadata/pallets/system/mod.go create mode 100644 metadata/pallets/transaction_payment/events.go create mode 100644 metadata/pallets/transaction_payment/mod.go create mode 100644 metadata/payload.go create mode 100644 metadata/types.go create mode 100644 primitives/address.go create mode 100644 primitives/already_encoded.go create mode 100644 primitives/block.go create mode 100644 primitives/extrinsics_decoded.go create mode 100644 primitives/extrinsics_encoded.go create mode 100644 primitives/extrinsics_payload.go create mode 100644 primitives/extrinsics_payload_test.go create mode 100644 primitives/extrinsics_sign.go create mode 100644 primitives/hash_h256.go create mode 100644 primitives/hash_h512.go create mode 100644 primitives/hash_h520.go create mode 100644 primitives/header.go create mode 100644 primitives/runtime_version.go create mode 100644 primitives/scale_decoder.go create mode 100644 primitives/scale_decoder_test.go create mode 100644 primitives/scale_encoder.go create mode 100644 primitives/scale_encoder_test.go create mode 100644 primitives/scale_hex.go create mode 100644 primitives/scale_types.go create mode 100644 primitives/signature.go create mode 100755 run_tests.sh create mode 100644 sdk.go delete mode 100644 src/config/config.go delete mode 100644 src/extrinsic/era.go delete mode 100644 src/extrinsic/extrinsic.go delete mode 100644 src/extrinsic/payload.go delete mode 100644 src/header/header.go delete mode 100644 src/rpc/block.go delete mode 100644 src/rpc/kate.go delete mode 100644 src/rpc/submit.go delete mode 100644 src/sdk/call/call.go delete mode 100644 src/sdk/callExtrinsic.go delete mode 100644 src/sdk/events.go delete mode 100644 src/sdk/helper.go delete mode 100644 src/sdk/sdk.go delete mode 100644 src/sdk/tx/transactions.go delete mode 100644 src/sdk/types/types.go delete mode 100644 src/sdk/types/ucompact.go diff --git a/complex/block.go b/complex/block.go new file mode 100644 index 0000000..0a24cfd --- /dev/null +++ b/complex/block.go @@ -0,0 +1,187 @@ +package complex + +import ( + meta "go-sdk/metadata" + daPallet "go-sdk/metadata/pallets/data_availability" + prim "go-sdk/primitives" +) + +type Block struct { + client *Client + Block RPCBlock + events prim.Option[EventRecords] +} + +func NewBlock(client *Client, blockHash prim.H256) Block { + block := client.GetBlock(prim.NewSome(blockHash)) + events, err := client.GetEvents(prim.NewSome(blockHash)) + if err != nil { + panic(err) + } + return Block{ + client: client, + Block: block, + events: prim.NewSome(events), + } +} + +func (this *Block) TransactionBySigner(accountId meta.AccountId) []BlockTransaction { + var result = []BlockTransaction{} + for _, tx := range this.Block.Extrinsics { + if !sameSignature(&tx, accountId) { + continue + } + result = append(result, NewBlockTransaction(this.client, &tx)) + } + + return result +} + +func (this *Block) TransactionByIndex(txIndex uint32) prim.Option[BlockTransaction] { + for _, tx := range this.Block.Extrinsics { + if tx.TxIndex == txIndex { + return prim.NewSome(NewBlockTransaction(this.client, &tx)) + } + } + + return prim.NewNone[BlockTransaction]() +} + +func (this *Block) TransactionByHash(txHash prim.H256) prim.Option[BlockTransaction] { + for _, tx := range this.Block.Extrinsics { + if tx.TxHash == txHash { + return prim.NewSome(NewBlockTransaction(this.client, &tx)) + } + } + + return prim.NewNone[BlockTransaction]() +} + +func (this *Block) TransactionByAppId(appId uint32) []BlockTransaction { + var result = []BlockTransaction{} + for _, tx := range this.Block.Extrinsics { + if tx.Signed.IsNone() { + continue + } + var signed = tx.Signed.Unwrap() + if signed.AppId != appId { + continue + } + result = append(result, NewBlockTransaction(this.client, &tx)) + } + + return result +} + +func (this *Block) DataSubmissionBySigner(accountId meta.AccountId) []DataSubmission { + var result = []DataSubmission{} + for _, tx := range this.Block.Extrinsics { + if !sameSignature(&tx, accountId) { + continue + } + + if res, ok := NewDataSubmission(&tx); ok { + result = append(result, res) + } + + } + + return result +} + +func (this *Block) DataSubmissionByIndex(txIndex uint32) prim.Option[DataSubmission] { + for _, tx := range this.Block.Extrinsics { + if tx.TxIndex != txIndex { + continue + } + if res, ok := NewDataSubmission(&tx); ok { + return prim.NewSome(res) + } + } + + return prim.NewNone[DataSubmission]() +} + +func (this *Block) DataSubmissionByHash(txHash prim.H256) prim.Option[DataSubmission] { + for _, tx := range this.Block.Extrinsics { + if tx.TxHash != txHash { + continue + } + if res, ok := NewDataSubmission(&tx); ok { + return prim.NewSome(res) + } + } + + return prim.NewNone[DataSubmission]() +} + +func (this *Block) DataSubmissionByAppId(appId uint32) []DataSubmission { + var result = []DataSubmission{} + for _, tx := range this.Block.Extrinsics { + if tx.Signed.IsNone() { + continue + } + var signed = tx.Signed.Unwrap() + if signed.AppId != appId { + continue + } + if res, ok := NewDataSubmission(&tx); ok { + result = append(result, res) + } + } + + return result +} + +func (this *Block) Events(appId uint32) prim.Option[EventRecords] { + return this.events +} + +func sameSignature(tx *prim.DecodedExtrinsic, accountId meta.AccountId) bool { + txAccountId := tx.Signed.UnwrapOrDefault().Address.Id.UnwrapOrDefault() + if accountId.Value != txAccountId { + return false + } + + return true +} + +type DataSubmission struct { + TxHash prim.H256 + TxIndex uint32 + Data []byte + TxSigner prim.MultiAddress + AppId uint32 +} + +func NewDataSubmission(tx *prim.DecodedExtrinsic) (DataSubmission, bool) { + ok := false + res := DataSubmission{} + + callSubmitData := daPallet.CallSubmitData{} + if tx.Call.PalletIndex != callSubmitData.PalletIndex() { + return res, ok + } + + if tx.Call.CallIndex != callSubmitData.CallIndex() { + return res, ok + } + + // Data submission cannot be done without signed being set. + signed := tx.Signed.UnwrapOrDefault() + + decoder := prim.NewDecoder(prim.FromHex(tx.Call.Fields.Value), 0) + if err := decoder.Decode(&callSubmitData); err != nil { + return res, false + } + + res = DataSubmission{ + TxHash: tx.TxHash, + TxIndex: tx.TxIndex, + Data: callSubmitData.Data, + TxSigner: signed.Address, + AppId: signed.AppId, + } + + return res, true +} diff --git a/complex/block_transaction.go b/complex/block_transaction.go new file mode 100644 index 0000000..3087ddd --- /dev/null +++ b/complex/block_transaction.go @@ -0,0 +1,63 @@ +package complex + +import ( + "go-sdk/interfaces" + prim "go-sdk/primitives" +) + +type BlockTransaction struct { + client *Client + Extrinsic *prim.DecodedExtrinsic + palletName string + callName string +} + +func NewBlockTransaction(client *Client, extrinsic *prim.DecodedExtrinsic) BlockTransaction { + names, err := client.Metadata().PalletCallName(extrinsic.Call.PalletIndex, extrinsic.Call.CallIndex) + if err != nil { + panic(err) + } + + return BlockTransaction{ + client: client, + Extrinsic: extrinsic, + palletName: names[0], + callName: names[1], + } +} + +func (this *BlockTransaction) CallData(data interfaces.CallDataT) prim.Option[interface{}] { + return data.Decode(this.Extrinsic.Call) +} + +func (this *BlockTransaction) PalletName() string { + return this.palletName +} + +func (this *BlockTransaction) CallName() string { + return this.callName +} + +func (this *BlockTransaction) PalletIndex() uint8 { + return this.Extrinsic.Call.PalletIndex +} + +func (this *BlockTransaction) CallIndex() uint8 { + return this.Extrinsic.Call.CallIndex +} + +func (this *BlockTransaction) TxHash() prim.H256 { + return this.Extrinsic.TxHash +} + +func (this *BlockTransaction) TxIndex() uint32 { + return this.Extrinsic.TxIndex +} + +func (this *BlockTransaction) Signed() prim.Option[prim.DecodedExtrinsicSigned] { + return this.Extrinsic.Signed +} + +func (this *BlockTransaction) Fields() prim.AlreadyEncoded { + return this.Extrinsic.Call.Fields +} diff --git a/complex/client.go b/complex/client.go new file mode 100644 index 0000000..46f7678 --- /dev/null +++ b/complex/client.go @@ -0,0 +1,158 @@ +package complex + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "go-sdk/metadata" + "io" + "net/http" + + meta "go-sdk/metadata" + prim "go-sdk/primitives" +) + +type Client struct { + client *http.Client + endpoint string + metadata *metadata.Metadata + Rpc RPC +} + +func NewClient(endpoint string) *Client { + client := new(Client) + client.client = new(http.Client) + client.endpoint = endpoint + client.Rpc = newRPC(client) + + return client +} + +func (this *Client) GetEvents(at prim.Option[prim.H256]) (EventRecords, error) { + eventsRaw := this.Rpc.State.GetEvents(at) + events, err := NewEvents(prim.FromHex(eventsRaw), this.Metadata()) + if err != nil { + return EventRecords{}, err + } + + eventRecord, err := events.Decode() + if err != nil { + return EventRecords{}, err + } + + return eventRecord, nil +} + +func (this *Client) InitMetadata(at prim.Option[prim.H256]) error { + scaleMetadata := this.Rpc.State.GetMetadata(at) + metadata, err := metadata.NewMetadata(scaleMetadata) + if err != nil { + return err + } + + this.metadata = &metadata + return nil +} + +func (this *Client) Request(method string, params string) (string, error) { + rawJSON := []byte(`{ + "id": 1, + "jsonrpc": "2.0", + "method": "%s", + "params": %s + }`) + + requestBodyString := fmt.Sprintf(string(rawJSON), method, params) + requestBodyBytes := []byte(requestBodyString) + + request, err := http.NewRequest("POST", this.endpoint, bytes.NewBuffer(requestBodyBytes)) + if err != nil { + return "", err + } + + request.Header.Add("Content-Type", "application/json") + response, err := this.client.Do(request) + if err != nil { + return "", err + } + + defer response.Body.Close() + + responseBodyBytes, _ := io.ReadAll(response.Body) + // fmt.Println("response Status:", response.Status) + // fmt.Println("response Headers:", response.Header) + // fmt.Println("response Body:", string(responseBodyBytes)) + + if response.StatusCode != http.StatusOK { + return "", errors.New("HTTP status was NOT OK") + } + + var mappedData map[string]interface{} + if err := json.Unmarshal(responseBodyBytes, &mappedData); err != nil { + return "", err + } + + if mappedData["error"] != nil { + err := mappedData["error"].(map[string]interface{}) + return "", errors.New(err["message"].(string) + ". " + err["data"].(string)) + } + + if mappedData["result"] == nil { + return "", errors.New("Failed to retrieve response result.") + } + + resultBytes, _ := json.Marshal(mappedData["result"]) + result := string(resultBytes) + + // Remove double quotes if there are any + if len(result) >= 1 { + if result[0] == '"' && result[len(result)-1] == '"' { + result = result[1 : len(result)-1] + } + } + + return result, nil +} + +func (this *Client) Send(tx prim.EncodedExtrinsic) prim.H256 { + params := "[\"" + tx.ToHexWith0x() + "\"]" + + txHash, err := this.Request("author_submitExtrinsic", params) + if err != nil { + panic(err.Error()) + } + + return prim.NewH256FromHexString(txHash) +} + +func (this *Client) GetBlock(blockHash prim.Option[prim.H256]) RPCBlock { + primBlock := this.Rpc.Chain.GetBlock(blockHash) + return NewRPCBlockFromPrimBlock(primBlock) +} + +func (this *Client) Metadata() *meta.Metadata { + return this.metadata +} + +type RPCBlock struct { + Header prim.Header + Extrinsics []prim.DecodedExtrinsic +} + +func NewRPCBlockFromPrimBlock(primBlock prim.Block) RPCBlock { + extrinsics := []prim.DecodedExtrinsic{} + for i := 0; i < len(primBlock.Extrinsics); i++ { + encoded := prim.NewEncodedExtrinsicFromHex(primBlock.Extrinsics[i]) + decoded, err := encoded.Decode(uint32(i)) + if err != nil { + panic(err) + } + extrinsics = append(extrinsics, decoded) + } + + return RPCBlock{ + Header: primBlock.Header, + Extrinsics: extrinsics, + } +} diff --git a/complex/events.go b/complex/events.go new file mode 100644 index 0000000..a80443a --- /dev/null +++ b/complex/events.go @@ -0,0 +1,287 @@ +package complex + +import ( + "errors" + "fmt" + "go-sdk/interfaces" + meta "go-sdk/metadata" + prim "go-sdk/primitives" +) + +type Events struct { + eventBytes []byte + metadata *meta.Metadata + startIdx uint32 /// Start index for events. Here we ignore the event count bytes + eventCount uint32 +} + +func NewEvents(eventBytes []byte, metadata *meta.Metadata) (Events, error) { + events := Events{} + + // Sanity Check + if len(eventBytes) == 0 { + return Events{}, nil + } + + // Decode EventCount + decoder := prim.NewDecoder(eventBytes, 0) + compactEventCount := prim.CompactU32{} + decoder.Decode(&compactEventCount) + + // Sanity Check. A stupid one but better than nothing + if events.eventCount > 1_000_000 { + return events, errors.New("Cannot decode events. Read garbage for event count") + } + + events.eventCount = compactEventCount.Value + events.startIdx = uint32(decoder.ScaleBytes.Offset) + events.eventBytes = eventBytes + events.metadata = metadata + + return events, nil +} + +func (this *Events) Decode() (EventRecords, error) { + result := EventRecords{} + position := 0 + + if this.eventCount == 0 { + return EventRecords{}, nil + } + + /* println("Event Count :", this.eventCount) */ + + decoder := prim.NewDecoder(this.eventBytes, int(this.startIdx)) + for { + eventRecord, err := NewEventRecord(&decoder, uint32(position), this.metadata) + if err != nil { + return EventRecords{}, err + } + + result = append(result, eventRecord) + position += 1 + + if position == int(this.eventCount) { + break + } + } + + /* println("Count: ", this.eventCount) */ + + // Sanity Check + if decoder.RemainingLength() != 0 { + //println("ISSUE: Remaining length: ", decoder.RemainingLength()) + return EventRecords{}, errors.New("All events were decoded but some bytes are left. This is not good.") + } + + return result, nil +} + +type EventPhase struct { + VariantIndex uint8 + ApplyExtrinsic prim.Option[uint32] +} + +func emptyEventPhase() EventPhase { + return EventPhase{ + VariantIndex: 0, + ApplyExtrinsic: prim.NewNone[uint32](), + } +} + +func (this *EventPhase) ToString() string { + switch this.VariantIndex { + case 0: + return "ApplyExtrinsic" + case 1: + return "Finalization" + case 2: + return "Initialization" + default: + panic("Unknown EventPhase Variant Index") + } +} + +func DecodeEventPhase(decoder *prim.Decoder) (EventPhase, error) { + + // Sanity check + if !decoder.HasAtLeastRemainingBytes(1) { + return EventPhase{}, errors.New("Failed to Decode Event Phase. Out of bytes") + } + + var eventPhase = emptyEventPhase() + decoder.Decode(&eventPhase.VariantIndex) + switch eventPhase.VariantIndex { + case 0: + // Sanity check + if !decoder.HasAtLeastRemainingBytes(4) { + return EventPhase{}, errors.New("Failed to Decode Event Phase. Out of bytes") + } + + var value = uint32(0) + decoder.Decode(&value) + eventPhase.ApplyExtrinsic.Set(value) + return eventPhase, nil + case 1: + return eventPhase, nil + case 2: + return eventPhase, nil + default: + return eventPhase, errors.New(fmt.Sprintf(`Failed to Decode Event Phase. Unknown Variant Index %v`, eventPhase.VariantIndex)) + } +} + +type EventRecords = []EventRecord + +type EventRecord struct { + Phase EventPhase + PalletIndex uint8 + EventIndex uint8 + PalletName string + EventName string + Position uint32 + AllBytes []byte + /// Phase, pallet/event index, fields and topic + StartIdx uint32 + /// (After Phase) pallet/event index, fields and topic + EventStartIndex uint32 + /// (After Phase, pallet/event index) fields and topic + EventFieldsStartIndex uint32 + /// End Of the fields (before topic) + EventFieldsEndIndex uint32 + /// end of everything + EndIdx uint32 + Metadata *meta.Metadata + Topics []prim.H256 +} + +func NewEventRecord(decoder *prim.Decoder, position uint32, metadata *meta.Metadata) (EventRecord, error) { + var eventRecord = EventRecord{} + + eventRecord.StartIdx = uint32(decoder.Offset()) + + /* println("Before Event Phase") */ + eventPhase, err := DecodeEventPhase(decoder) + if err != nil { + return EventRecord{}, err + } + eventRecord.Phase = eventPhase + /* println("Before After Phase") */ + + // Pallet and Event Index Decoding + + eventRecord.EventStartIndex = uint32(decoder.Offset()) + if err := decoder.Decode(&eventRecord.PalletIndex); err != nil { + return EventRecord{}, err + } + if err := decoder.Decode(&eventRecord.EventIndex); err != nil { + return EventRecord{}, err + } + + // Decoding Pallet and Event Names + names, err := metadata.PalletEventName(eventRecord.PalletIndex, eventRecord.EventIndex) + if err != nil { + return EventRecord{}, err + } + eventRecord.PalletName = names[0] + eventRecord.EventName = names[1] + + // println(fmt.Sprintf(`Decoding %v, %v %v`, eventRecord.PalletName, eventRecord.EventName, eventRecord.Phase.ToString())) + + // Decode Fields + eventRecord.EventFieldsStartIndex = uint32(decoder.Offset()) + if err := metadata.DecodeEvent(eventRecord.PalletIndex, eventRecord.EventIndex, decoder); err != nil { + return EventRecord{}, err + } + eventRecord.EventFieldsEndIndex = uint32(decoder.Offset()) + /* println("Before topics") + + println(fmt.Sprintf(`EventFieldsStartIndexed %v`, eventRecord.EventFieldsStartIndex)) + println(fmt.Sprintf(`EventFieldsEndIndex %v`, eventRecord.EventFieldsEndIndex)) */ + + // Decode Topics + if err := decoder.Decode(&eventRecord.Topics); err != nil { + return EventRecord{}, err + } + /* println("After topics") */ + + eventRecord.EndIdx = uint32(decoder.Offset()) + eventRecord.AllBytes = decoder.ScaleBytes.Data + eventRecord.Metadata = metadata + eventRecord.Position = position + + // TODO + /* println(fmt.Sprintf(`Decoded %v, %v`, eventRecord.PalletName, eventRecord.EventName)) + println(fmt.Sprintf(`Decoded %v`, eventRecord.Phase.ToString())) */ + /* println(fmt.Sprintf(`EventFieldsStartIndexed %v`, eventRecord.EventFieldsStartIndex)) + println(fmt.Sprintf(`EventFieldsEndIndex %v`, eventRecord.EventFieldsEndIndex)) */ + + return eventRecord, nil +} + +func FindFirst[T interfaces.EventT](eventRecords EventRecords, target T) prim.Option[T] { + for _, elem := range eventRecords { + if elem.PalletIndex != target.PalletIndex() { + continue + } + if elem.EventIndex != target.EventIndex() { + continue + } + + var t T + var decoder = prim.NewDecoder(elem.AllBytes[elem.EventFieldsStartIndex:elem.EventFieldsEndIndex], 0) + if decoder.Decode(&t) != nil { + panic("Failed to Decode in Events.FindFirst") + } + return prim.NewSome(t) + } + + return prim.NewNone[T]() +} + +func FindAll[T interfaces.EventT](eventRecords EventRecords, target T) []T { + var t T + var result = []T{} + for _, elem := range eventRecords { + if elem.PalletIndex != target.PalletIndex() { + continue + } + if elem.EventIndex != target.EventIndex() { + continue + } + + var decoder = prim.NewDecoder(elem.AllBytes[elem.EventFieldsStartIndex:elem.EventFieldsEndIndex], 0) + if decoder.Decode(&t) != nil { + panic("Failed to Decode in Events.FindAll") + } + result = append(result, t) + } + + return result +} + +func FindLast[T interfaces.EventT](eventRecords EventRecords, target T) prim.Option[T] { + var result = FindAll(eventRecords, target) + if len(result) == 0 { + return prim.NewNone[T]() + } + + return prim.NewSome(result[len(result)-1]) +} + +func FilterByTxIndex(eventRecords EventRecords, txIndex uint32) EventRecords { + var result = EventRecords{} + for _, elem := range eventRecords { + if elem.Phase.ApplyExtrinsic.IsNone() { + continue + } + var elemTxIndex = elem.Phase.ApplyExtrinsic.Unwrap() + if elemTxIndex != txIndex { + continue + } + + result = append(result, elem) + } + + return result +} diff --git a/complex/rpc.go b/complex/rpc.go new file mode 100644 index 0000000..e540959 --- /dev/null +++ b/complex/rpc.go @@ -0,0 +1,74 @@ +package complex + +import ( + prim "go-sdk/primitives" + "strconv" +) + +type RPC struct { + client *Client + System systemRPC + State stateRPC + Chain chainRPC + ChainSpec chainSpecRPC +} + +func newRPC(client *Client) RPC { + return RPC{ + client: client, + System: systemRPC{client: client}, + State: stateRPC{client: client}, + Chain: chainRPC{client: client}, + ChainSpec: chainSpecRPC{client: client}, + } +} + +type systemRPC struct { + client *Client +} + +type stateRPC struct { + client *Client +} + +type chainRPC struct { + client *Client +} + +type chainSpecRPC struct { + client *Client +} + +type RPCParams struct { + Values []string +} + +func (this *RPCParams) Add(value string) { + this.Values = append(this.Values, value) +} + +func (this *RPCParams) AddH256(value prim.H256) { + this.Add(value.ToRpcParam()) +} + +func (this *RPCParams) AddUint32(value uint32) { + this.Add(strconv.FormatUint(uint64(value), 10)) +} + +func (this *RPCParams) Build() string { + length := len(this.Values) + if length == 0 { + return "[]" + } + + result := "[" + for i := 0; i < length; i++ { + result += this.Values[i] + if i < (length - 1) { + result += ", " + } + } + result += "]" + + return result +} diff --git a/complex/rpc_chain.go b/complex/rpc_chain.go new file mode 100644 index 0000000..ee4bb68 --- /dev/null +++ b/complex/rpc_chain.go @@ -0,0 +1,55 @@ +package complex + +import ( + prim "go-sdk/primitives" +) + +func (this *chainRPC) GetBlock(blockHash prim.Option[prim.H256]) prim.Block { + params := RPCParams{} + if blockHash.IsSome() { + params.AddH256(blockHash.Unwrap()) + } + value, err := this.client.Request("chain_getBlock", params.Build()) + if err != nil { + panic(err) + } + + return prim.NewBlock(value) +} + +func (this *chainRPC) GetBlockHash(blockNumber prim.Option[uint32]) prim.H256 { + params := RPCParams{} + if blockNumber.IsSome() { + params.AddUint32(blockNumber.Unwrap()) + } + value, err := this.client.Request("chain_getBlockHash", params.Build()) + if err != nil { + panic(err) + } + + return prim.NewH256FromHexString(value) +} + +func (this *chainRPC) GetFinalizedHead() prim.H256 { + params := RPCParams{} + value, err := this.client.Request("chain_getFinalizedHead", params.Build()) + if err != nil { + panic(err) + } + + return prim.NewH256FromHexString(value) + +} + +func (this *chainRPC) GetHeader(blockHash prim.Option[prim.H256]) prim.Header { + params := RPCParams{} + if blockHash.IsSome() { + params.AddH256(blockHash.Unwrap()) + } + headerRaw, err := this.client.Request("chain_getHeader", params.Build()) + if err != nil { + panic(err) + } + + return prim.NewHeaderFromJson(headerRaw) +} diff --git a/complex/rpc_chain_spec.go b/complex/rpc_chain_spec.go new file mode 100644 index 0000000..27278ec --- /dev/null +++ b/complex/rpc_chain_spec.go @@ -0,0 +1,15 @@ +package complex + +import ( + prim "go-sdk/primitives" +) + +func (this *chainSpecRPC) V1GenesisHash() prim.H256 { + params := RPCParams{} + value, err := this.client.Request("chainSpec_v1_genesisHash", params.Build()) + if err != nil { + panic(err) + } + + return prim.NewH256FromHexString(value) +} diff --git a/complex/rpc_state.go b/complex/rpc_state.go new file mode 100644 index 0000000..ee2fbce --- /dev/null +++ b/complex/rpc_state.go @@ -0,0 +1,63 @@ +package complex + +import ( + prim "go-sdk/primitives" +) + +func (this *stateRPC) GetRuntimeVersion(blockHash prim.Option[prim.H256]) prim.RuntimeVersion { + var params = &RPCParams{} + if blockHash.IsSome() { + params.AddH256(blockHash.Unwrap()) + } + + var value, err = this.client.Request("state_getRuntimeVersion", params.Build()) + if err != nil { + panic(err) + } + + return prim.NewRuntimeVersionFromJson(value) +} + +func (this *stateRPC) GetStorage(key string, at prim.Option[prim.H256]) string { + params := RPCParams{} + params.Add("\"" + key + "\"") + if at.IsSome() { + params.AddH256(at.Unwrap()) + } + + value, err := this.client.Request("state_getStorage", params.Build()) + if err != nil { + panic(err) + } + + return value +} + +func (this *stateRPC) GetMetadata(at prim.Option[prim.H256]) string { + params := RPCParams{} + if at.IsSome() { + params.AddH256(at.Unwrap()) + } + + value, err := this.client.Request("state_getMetadata", params.Build()) + if err != nil { + panic(err) + } + + return value +} + +func (this *stateRPC) GetEvents(at prim.Option[prim.H256]) string { + params := RPCParams{} + params.Add("\"" + "0x26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7" + "\"") + if at.IsSome() { + params.AddH256(at.Unwrap()) + } + + value, err := this.client.Request("state_getStorage", params.Build()) + if err != nil { + return "" + } + + return value +} diff --git a/complex/rpc_system.go b/complex/rpc_system.go new file mode 100644 index 0000000..b164553 --- /dev/null +++ b/complex/rpc_system.go @@ -0,0 +1,33 @@ +package complex + +import ( + "strconv" +) + +func (this *systemRPC) AccountNextIndex(accountId string) uint32 { + if len(accountId) < 1 { + panic("AccountId needs to have a length of > 0") + } + + if accountId[0] != '"' { + accountId = "\"" + accountId + } + + if accountId[len(accountId)-1] != '"' { + accountId += "\"" + } + + params := RPCParams{} + params.Add(accountId) + + value, err := this.client.Request("system_accountNextIndex", params.Build()) + if err != nil { + panic(err) + } + parsedValue, err := strconv.ParseUint(value, 10, 32) + if err != nil { + panic(err) + } + + return uint32(parsedValue) +} diff --git a/complex/transaction.go b/complex/transaction.go new file mode 100644 index 0000000..78d2cd5 --- /dev/null +++ b/complex/transaction.go @@ -0,0 +1,153 @@ +package complex + +import ( + "strconv" + "time" + + "github.com/vedhavyas/go-subkey/v2" + + "go-sdk/metadata" + prim "go-sdk/primitives" +) + +type Transaction struct { + Client *Client + Payload metadata.Payload +} + +func NewTransaction(client *Client, payload metadata.Payload) Transaction { + return Transaction{ + Client: client, + Payload: payload, + } +} + +func (this *Transaction) Execute(account subkey.KeyPair, options TransactionOptions) prim.H256 { + return TransactionSignAndSend(this.Client, account, this.Payload, options) +} + +func (this *Transaction) ExecuteAndWatch(account subkey.KeyPair, waitForFin bool, options TransactionOptions) TransactionDetails { + return TransactionSignSendWatch(this.Client, account, this.Payload, waitForFin, options) +} + +func (this *Transaction) ExecuteAndWatchFinalization(account subkey.KeyPair, options TransactionOptions) TransactionDetails { + return TransactionSignSendWatch(this.Client, account, this.Payload, true, options) +} + +func (this *Transaction) ExecuteAndWatchInclusion(account subkey.KeyPair, options TransactionOptions) TransactionDetails { + return TransactionSignSendWatch(this.Client, account, this.Payload, false, options) +} + +func TransactionSignAndSend(client *Client, account subkey.KeyPair, payload metadata.Payload, options TransactionOptions) prim.H256 { + var extra, additional = options.ToPrimitive(client, account.SS58Address(42)) + var tx = prim.CreateSigned(payload.Call, extra, additional, account) + + return client.Send(tx) +} + +func TransactionSignSendWatch(client *Client, account subkey.KeyPair, payload metadata.Payload, waitForFin bool, options TransactionOptions) TransactionDetails { + var extra, additional = options.ToPrimitive(client, account.SS58Address(42)) + var tx = prim.CreateSigned(payload.Call, extra, additional, account) + + var retryCount = 2 + for { + var txHash = client.Send(tx) + var maybeDetails = TransactionWatch(client, txHash, waitForFin) + if maybeDetails.IsSome() { + return maybeDetails.Unwrap() + } + + retryCount -= 1 + if retryCount == 0 { + break + } + } + + panic("Something went wrong :(") +} + +type TransactionDetails struct { + Client *Client + TxHash prim.H256 + TxIndex uint32 + BlockHash prim.H256 + BlockNumber uint32 + Events prim.Option[EventRecords] +} + +func TransactionWatch(client *Client, txHash prim.H256, waitForFin bool) prim.Option[TransactionDetails] { + shouldSleep := false + currentBlockHash := prim.NewNone[prim.H256]() + timeoutBlockNumber := prim.NewNone[uint32]() + bTimeout := uint32(3) + if waitForFin { + bTimeout = uint32(5) + } + + if waitForFin { + println("Watching for Tx Hash: " + txHash.ToHexWith0x() + ", Waiting for finalization") + } else { + println("Watching for Tx Hash: " + txHash.ToHexWith0x() + ", Waiting for inclusion") + } + + for { + if shouldSleep { + time.Sleep(time.Second * 3) + } + if !shouldSleep { + shouldSleep = true + } + + blockHash := prim.H256{} + if waitForFin { + blockHash = client.Rpc.Chain.GetFinalizedHead() + } else { + blockHash = client.Rpc.Chain.GetBlockHash(prim.NewNone[uint32]()) + } + + if currentBlockHash.IsSome() { + if currentBlockHash.Unwrap() == blockHash { + continue + } + } + currentBlockHash = prim.NewSome(blockHash) + + block := client.GetBlock(prim.NewSome(blockHash)) + blockNumber := block.Header.Number + println("New Block fetched. Hash: " + blockHash.ToHexWith0x() + ", Number: " + strconv.FormatUint(uint64(blockNumber), 10)) + + for _, element := range block.Extrinsics { + if element.TxHash.ToHexWith0x() == txHash.ToHexWith0x() { + // Get Events + events, err := client.GetEvents(prim.NewSome(blockHash)) + if err != nil { + panic(err) + } + events = FilterByTxIndex(events, element.TxIndex) + + details := TransactionDetails{ + TxHash: txHash, + TxIndex: element.TxIndex, + BlockHash: blockHash, + BlockNumber: blockNumber, + Events: prim.NewSome(events), + } + return prim.NewSome(details) + } + } + + if timeoutBlockNumber.IsNone() { + timeoutBlockNumber = prim.NewSome(blockNumber + bTimeout) + println("Current Block Number: " + strconv.FormatUint(uint64(blockNumber), 10) + ", Timeout Block Number: " + strconv.FormatUint(uint64(blockNumber+bTimeout+1), 10)) + } + + if timeoutBlockNumber.IsSome() { + timeoutBlock := timeoutBlockNumber.Unwrap() + if timeoutBlock < blockNumber { + break + } + } + } + + return prim.NewNone[TransactionDetails]() +} diff --git a/complex/transaction_options.go b/complex/transaction_options.go new file mode 100644 index 0000000..5460f73 --- /dev/null +++ b/complex/transaction_options.go @@ -0,0 +1,57 @@ +package complex + +import ( + prim "go-sdk/primitives" + "math/big" + + "github.com/itering/scale.go/utiles/uint128" +) + +type TransactionOptions struct { + AppId prim.Option[uint32] + Nonce prim.Option[uint32] +} + +func NewTransactionOptions() TransactionOptions { + return TransactionOptions{ + AppId: prim.NewNone[uint32](), + Nonce: prim.NewNone[uint32](), + } +} + +func (this TransactionOptions) WithAppId(value uint32) TransactionOptions { + this.AppId = prim.NewSome(value) + return this +} + +func (this TransactionOptions) WithNonce(value uint32) TransactionOptions { + this.Nonce = prim.NewSome(value) + return this +} + +func (this *TransactionOptions) ToPrimitive(client *Client, accountAddress string) (prim.Extra, prim.Additional) { + genesisHash := client.Rpc.ChainSpec.V1GenesisHash() + forkHash := client.Rpc.Chain.GetBlockHash(prim.NewNone[uint32]()) + forBlockNumber := client.Rpc.Chain.GetHeader(prim.NewSome(forkHash)).Number + + runtimeVersion := client.Rpc.State.GetRuntimeVersion(prim.NewNone[prim.H256]()) + + additional := prim.Additional{ + SpecVersion: runtimeVersion.SpecVersion, + TxVersion: runtimeVersion.TxVersion, + GenesisHash: genesisHash, + ForkHash: forkHash, + } + + extra := prim.Extra{} + extra.AppId = this.AppId.Unwrap0rElse(uint32(0)) + extra.Tip = uint128.FromBig(big.NewInt(0)) + if this.Nonce.IsNone() { + extra.Nonce = client.Rpc.System.AccountNextIndex(accountAddress) + } else { + extra.Nonce = this.Nonce.Unwrap() + } + extra.Era = prim.NewEra(32, uint64(forBlockNumber)) + + return extra, additional +} diff --git a/examples/README.md b/examples/README.md deleted file mode 100644 index 377aece..0000000 --- a/examples/README.md +++ /dev/null @@ -1,991 +0,0 @@ -# Avail Go SDK documentation / examples - -## Running Examples in the Docs Directory - -To run the examples provided in the `/examples` directory, follow these steps: - -1. [Install](https://go.dev/doc/install) go globally if you haven't already: - -2. From the avail-go/examples, install all necessary dependencies: - -```bash -go mod tidy -``` - -3. Ensure that a config file is generated in the root of go-examples folder - -for example - -```json -{ - "seed": "bottom drive obey lake curtain smoke basket hold race lonely fit walk//Alice", - "api_url": "ws://127.0.0.1:9944", - "size": 1000, - "app_id": 0, - "dest": "5H3qehpRTFiB3XwyTzYU43SpG7e8jW87vFug95fxdew76Vyi", - "amount": 10 -} -``` - -4. Ensure you're running a local Avail node. You can do this with the following command from the root directory: - -```bash -cargo build --release -./target/release/avail-node --dev -``` - -You can also take the latest release from [Github](https://github.com/availproject/avail/releases) - -5. To run any example script from the examples/go-examples folder, use the following command format, replacing NAME_OF_THE_FILE with the actual file name you want to run: - -```bash -go run extrinsicFoldername/main.go --config config.json -``` - -For example, to run the staking_nominate.ts script: - -```bash -go run dataSubmit/main.go --config config.json -``` - -This will execute the chosen example script, showcasing how to interact with the Avail network using the avail-js-sdk. - -# Data Availability - -Runtime Component: DataAvailability\ -Runtime Index: 29\ -Interface Module Name: dataAvailability - -## Create Application Key - -Origin Level: Signed - -### Interface - -```go -func CreateApplicationKey(api *sdk.SubstrateAPI, seed string, data string, WaitForInclusion sdk.WaitFor) (types.Hash, types.Hash, error) -``` - -#### Parameters - -| parameter | type | optional | description | -| ---------------- | -------- | -------- | ------------------------------------------------------ | -| api | API | false | api for avail chain | -| WaitForInclusion | WaitFor | false | wait for block inclusion or finalization | -| Seed | Mnemonic | false | seed of the account that needs to sign the transaction | -| data | string | false | name of the application key | - -#### Return value - -On failure, a reason of failure is returned. On Success, ApplicationKeyCreated event, transaction hash and block hash is returned. - -### Minimal Example - -```go -package main - -import ( - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/tx" - - "fmt" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - - fmt.Println("Submitting data ...") - WaitFor := sdk.BlockInclusion - blockHash, txHash, err := tx.CreateApplicationKey(api, config.Seed, "my happyyy", WaitFor) - if err != nil { - fmt.Printf("cannot create application key:%v", err) - } - fmt.Printf("Application key created successfully with block hash: %v\n and ext hash:%v\n", blockHash.Hex(), txHash.Hex()) - sdk.EventParser(api, blockHash, "ApplicationKeyCreated") -} -``` - -## Submit Data - -Origin Level: Signed - -### Interface - -```go -func SubmitData(api *sdk.SubstrateAPI, seed string, AppID int, data string, WaitForInclusion sdk.WaitFor) (types.Hash, types.Hash, error) -``` - -#### Parameters - -| parameter | type | optional | description | -| ---------------- | ------------- | -------- | ------------------------------------------------------ | -| api | API | false | api for avail chain | -| WaitForInclusion | WaitFor | false | wait for block inclusion or finalization | -| Seed | Mnemonic | false | seed of the account that needs to sign the transaction | -| data | SignerOptions | true | data to be submitted | -| AppID | SignerOptions | true | AppID in which the transaction needs to be signed | - -#### Return value - -On failure, a reason of failure is returned. On Success, DataSubmitted event, transaction data, transaction hash and block hash is returned. - -### Minimal Example - -```go -package main - -import ( - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/tx" - - "fmt" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - - appID := 0 - - // if app id is greater than 0 then it must be created before submitting data - if config.AppID != 0 { - appID = config.AppID - } - fmt.Println("Submitting data ...") - WaitFor := sdk.BlockInclusion - - BlockHash, txHash, err := tx.SubmitData(api, config.Seed, appID, "my happy data", WaitFor) - if err != nil { - fmt.Printf("cannot submit data:%v", err) - } - fmt.Printf("Data submitted successfully with block hash: %v\n and ext hash:%v", BlockHash.Hex(), txHash.Hex()) -} -``` - -## Submit Block Length Proposal - -Origin Level: Root - -### Interface - -```go -func SubmitBlockLength(api *sdk.SubstrateAPI, seed string, WaitForInclusion sdk.WaitFor, rows uint32, cols uint32) (types.Hash, types.Hash, error) -``` - -#### Parameters - -| parameter | type | optional | description | -| ---------------- | -------- | -------- | ------------------------------------------------------ | -| api | API | false | api for avail chain | -| rows | number | false | number of rows in block | -| cols | number | false | number of cols in block | -| WaitForInclusion | WaitFor | false | wait for block inclusion or finalization | -| Seed | Mnemonic | false | seed of the account that needs to sign the transaction | - -#### Return value - -On failure, a reason of failure is returned. On Success, transaction hash and block hash is returned. - -### Minimal Example - -```go -package main - -import ( - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/tx" - - "fmt" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - - fmt.Println("Submitting data ...") - WaitFor := sdk.BlockInclusion - rows := uint32(128) - cols := uint32(128) - blockHash, txHash, err := tx.SubmitBlockLength(api, config.Seed, WaitFor, rows, cols) - if err != nil { - fmt.Printf("cannot submit block length:%v", err) - } - fmt.Printf("Block Length updated successfully with block hash: %v\n and ext hash:%v\n", blockHash.Hex(), txHash.Hex()) -} -``` - -## Set Application Key - -Origin Level: Root - -### Interface - -```go -func SetApplicationKey(api *sdk.SubstrateAPI, seed string, WaitForInclusion sdk.WaitFor, oldKey string, newKey string) (types.Hash, types.Hash, error) -``` - -#### Parameters - -| parameter | type | optional | description | -| ---------------- | -------- | -------- | ------------------------------------------------------ | -| api | API | false | api for avail chain | -| oldKey | string | false | application key to be replaced | -| newKey | string | false | application key that will replace the old one | -| WaitForInclusion | WaitFor | false | wait for block inclusion or finalization | -| Seed | Mnemonic | false | seed of the account that needs to sign the transaction | - -#### Return value - -On failure, a reason of failure is returned. On Success, ApplicationKeySet event, transaction hash and block hash is returned. - -### Minimal Example - -```go -package main - -import ( - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/tx" - - "fmt" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - fmt.Println("Submitting data ...") - WaitFor := sdk.BlockInclusion - newKey := "newKey" - oldKey := "oldKey" - blockHash, txHash, err := tx.SetApplicationKey(api, config.Seed, WaitFor, oldKey, newKey) - if err != nil { - fmt.Printf("cannot set key:%v", err) - } - fmt.Printf("Application Key updated successfully with block hash: %v\n and ext hash:%v\n", blockHash.Hex(), txHash.Hex()) - sdk.EventParser(api, blockHash, "ApplicationKeySet") -} -``` - -## Set Submit Data Fee Modifer - -Origin Level: Root - -### Interface - -```go -func SetSubmitDataFeeModifier(api *sdk.SubstrateAPI, seed string, WaitForInclusion sdk.WaitFor, modifier sdk.DispatchFeeModifier) (types.Hash, types.Hash, error) -``` - -#### Parameters - -| parameter | type | optional | description | -| ---------------- | ------------------- | -------- | ------------------------------------------------------ | -| api | API | false | api for avail chain | -| modifier | DispatchFeeModifier | false | new fee modifier values | -| WaitForInclusion | WaitFor | false | wait for block inclusion or finalization | -| Seed | Mnemonic | false | seed of the account that needs to sign the transaction | - -#### Return value - -On failure, a reason of failure is returned. On Success, transaction hash and block hash is returned. - -### Minimal Example - -```go -package main - -import ( - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/tx" - "math/big" - - "fmt" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - tenPow18 := new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil) - - weightMaximumFee := sdk.NewU128(tenPow18) - weightFeeDivider := sdk.NewU32(20) - weightFeeMultiplier := sdk.NewU32(1) - - // Create the DispatchFeeModifier - modifier := sdk.DispatchFeeModifier{ - WeightMaximumFee: weightMaximumFee, - WeightFeeDivider: weightFeeDivider, - WeightFeeMultiplier: weightFeeMultiplier, - } - fmt.Println("Submitting data ...") - WaitFor := sdk.BlockInclusion - // submit data - blockHash, txHash, err := tx.SetSubmitDataFeeModifier(api, config.Seed, WaitFor, modifier) - if err != nil { - fmt.Printf("cannot update DA fee:%v", err) - } - fmt.Printf("Data Fee modified successfully with block hash: %v\n and ext hash:%v\n", blockHash.Hex(), txHash.Hex()) -} -``` - -## Type Definitions - -```go -type WaitFor int - -const ( - BlockInclusion WaitFor = iota + 1 - BlockFinalization -) -``` - -```go -type DispatchFeeModifier struct { - WeightMaximumFee types.U128 - WeightFeeDivider types.U32 - WeightFeeMultiplier types.U32 -} -``` - -# Balances - -Runtime Component: Balances\ -Runtime Index: 6\ -Interface Module Name: balances - -## Transfer Keep Alive - -Origin Level: Signed - -### Interface - -```go -func TransferKeepAlive(api *sdk.SubstrateAPI, seed string, WaitForInclusion sdk.WaitFor, dest string, amount types.UCompact) (types.Hash, types.Hash, error) -``` - -#### Parameters - -| parameter | type | optional | description | -| ---------------- | -------- | -------- | ------------------------------------------------------ | -| api | API | false | api for avail chain | -| dest | string | false | account that will receive funds | -| amount | Ucompact | false | amount that is send. 10^18 is equal to 1 AVL | -| WaitForInclusion | WaitFor | false | wait for block inclusion or finalization | -| Seed | Mnemonic | false | seed of the account that needs to sign the transaction | - -#### Return value - -On failure, a reason of failure is returned. On Success, TransferEvent event, transaction hash and block hash is returned. - -### Minimal Example - -```go -package main - -import ( - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/tx" - "github.com/availproject/avail-go-sdk/src/sdk/types" - "math" - - "fmt" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - WaitFor := sdk.BlockInclusion - - amount := uint64(math.Pow(10, 18)) * 10 // send amount 10 AVAIL - dest := "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty" - bondAmountUCompact := types.NewUCompactFromUInt(amount) - BlockHash, txHash, err := tx.TransferKeepAlive(api, config.Seed, WaitFor, dest, bondAmountUCompact) - if err != nil { - fmt.Printf("cannot submit Transaction:%v", err) - } - fmt.Printf("Transaction submitted successfully with block hash: %v\n and ext hash:%v", BlockHash.Hex(), txHash.Hex()) - sdk.EventParser(api, BlockHash, "BalanceTransfer") -} -``` - -## Transfer Allow Death - -Origin Level: Signed - -### Interface - -```go -func TransferAllowDeath(api *sdk.SubstrateAPI, seed string, WaitForInclusion sdk.WaitFor, dest string, amount types.UCompact) (types.Hash, types.Hash, error) -``` - -#### Parameters - -| parameter | type | optional | description | -| ---------------- | -------- | -------- | ------------------------------------------------------ | -| api | API | false | api for avail chain | -| dest | string | false | account that will receive funds | -| amount | Ucompact | false | amount that is send. 10^18 is equal to 1 AVL | -| WaitForInclusion | WaitFor | false | wait for block inclusion or finalization | -| Seed | Mnemonic | false | seed of the account that needs to sign the transaction | - -#### Return value - -On failure, a reason of failure is returned. On Success, TransferEvent event, KilledAccount (optionally) event, transaction hash and block -hash is returned. - -### Minimal Example - -```go -package main - -import ( - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/tx" - "github.com/availproject/avail-go-sdk/src/sdk/types" - "math" - - "fmt" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - WaitFor := sdk.BlockInclusion - - amount := uint64(math.Pow(10, 18)) * 10 // send amount 10 AVAIL - dest := "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty" - bondAmountUCompact := types.NewUCompactFromUInt(amount) - BlockHash, txHash, err := tx.TransferAllowDeath(api, config.Seed, WaitFor, dest, bondAmountUCompact) - if err != nil { - fmt.Printf("cannot submit Transaction:%v", err) - } - fmt.Printf("Transaction submitted successfully with block hash: %v\n and ext hash:%v", BlockHash.Hex(), txHash.Hex()) - sdk.EventParser(api, BlockHash, "BalanceTransfer") -} -``` - -## Transfer All - -Origin Level: Signed - -### Interface - -```go -func TransferAll(api *sdk.SubstrateAPI, seed string, WaitForInclusion sdk.WaitFor, dest string) (types.Hash, types.Hash, error) -``` - -#### Parameters - -| parameter | type | optional | description | -| ---------------- | -------- | -------- | ------------------------------------------------------ | -| api | API | false | api for avail chain | -| dest | string | false | account that will receive funds | -| WaitForInclusion | WaitFor | false | wait for block inclusion or finalization | -| Seed | Mnemonic | false | seed of the account that needs to sign the transaction | - -#### Return value - -On failure, a reason of failure is returned. On Success transaction hash and block hash is returned. - -### Minimal Example - -```go -package main - -import ( - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/tx" - - "fmt" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - WaitFor := sdk.BlockInclusion - - dest := "5GNJqTPyNqANBkUVMN1LPPrxXnFouWXoe2wNSmmEoLctxiZY" - BlockHash, txHash, err := tx.TransferAll(api, config.Seed, WaitFor, dest) - if err != nil { - fmt.Printf("cannot submit Transaction:%v", err) - } - fmt.Printf("Transaction submitted successfully with block hash: %v\n and ext hash:%v", BlockHash.Hex(), txHash.Hex()) -} -``` - -# Staking - -Runtime Component: Staking\ -Runtime Index: 10\ -Interface Module Name: staking - -### Type Definitions - -```go -type Payee uint8 - -const ( -Staked WaitFor = iota -Stash -Controller -Account -None -) -``` - -## Bond - -Origin Level: Signed - -### Interface - -```go -func Bond(api *sdk.SubstrateAPI, seed string, WaitForInclusion sdk.WaitFor, amount types.UCompact, Payee sdk.Payee) (types.Hash, types.Hash, error) -``` - -#### Parameters - -| parameter | type | optional | description | -| ---------------- | -------- | -------- | ------------------------------------------------------- | -| api | API | false | api for avail chain | -| amount | Ucompact | false | amount that is bond. | -| payee | Payee | false | Can be: "Staked", "Stash", "None" or an account address | -| WaitForInclusion | WaitFor | false | wait for block inclusion or finalization | -| Seed | Mnemonic | false | seed of the account that needs to sign the transaction | - -#### Return value - -On failure, a reason of failure is returned. On Success, Bonded event, transaction hash and block hash is returned. - -### Minimal Example - -```go -package main - -import ( - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/tx" - - "fmt" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - WaitFor := sdk.BlockInclusion - Payee := sdk.Staked - - bondAmount := int64(1000) - - BlockHash, txHash, err := tx.Bond(api, config.Seed, WaitFor, bondAmount, sdk.Payee(Payee)) - if err != nil { - fmt.Printf("cannot submit Transaction:%v", err) - } - fmt.Printf("Transaction submitted successfully with block hash: %v\n and ext hash:%v", BlockHash.Hex(), txHash.Hex()) - sdk.EventParser(api, BlockHash, "Bond") -} -``` - -## Bond Extra - -Origin Level: Signed - -### Interface - -```go -func BondExtra(api *sdk.SubstrateAPI, seed string, WaitForInclusion sdk.WaitFor, amount types.UCompact) (types.Hash, types.Hash, error) -``` - -#### Parameters - -| parameter | type | optional | description | -| ---------------- | ----------- | -------- | ------------------------------------------------------- | -| api | API | false | api for avail chain | -| amount | Ucompact | false | additional amount that is bond. 10^18 is equal to 1 AVL | -| WaitForInclusion | WaitFor | false | wait for block inclusion or finalization | -| account | KeyringPair | false | account that will send and sign the transaction | -| Seed | Mnemonic | false | seed of the account that needs to sign the transaction | - -#### Return value - -On failure, a reason of failure is returned. On Success, transaction hash and block hash is returned. - -### Minimal Example - -```go -package main - -import ( - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/tx" - - "fmt" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - WaitFor := sdk.BlockInclusion - - bondAmount := int64(1000) - - BlockHash, txHash, err := tx.BondExtra(api, config.Seed, WaitFor, bondAmount) - if err != nil { - fmt.Printf("cannot submit Transaction:%v", err) - } - fmt.Printf("Transaction submitted successfully with block hash: %v\n and ext hash:%v", BlockHash.Hex(), txHash.Hex()) -} -``` - -## Chill - -Origin Level: Signed - -### Interface - -```go -func Chill(api *sdk.SubstrateAPI, seed string, WaitForInclusion sdk.WaitFor) (types.Hash, types.Hash, error) -``` - -#### Parameters - -| parameter | type | optional | description | -| ---------------- | -------- | -------- | ------------------------------------------------------ | -| WaitForInclusion | WaitFor | false | wait for block inclusion or finalization | -| api | API | false | api for avail chain | -| Seed | Mnemonic | false | seed of the account that needs to sign the transaction | - -#### Return value - -On failure, a reason of failure is returned. On Success, transaction hash and block hash is returned. - -### Minimal Example - -```go -package main - -import ( - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/tx" - - "fmt" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - WaitFor := sdk.BlockInclusion - - BlockHash, txHash, err := tx.Chill(api, config.Seed, WaitFor) - if err != nil { - fmt.Printf("cannot submit Transaction:%v", err) - } - fmt.Printf("Transaction submitted successfully with block hash: %v\n and ext hash:%v", BlockHash.Hex(), txHash.Hex()) -} -``` - -## Chill Other - -Origin Level: Signed - -### Interface - -```go -func ChillOther(api *sdk.SubstrateAPI, seed string, WaitForInclusion sdk.WaitFor, stash string) (types.Hash, types.Hash, error) -``` - -#### Parameters - -| parameter | type | optional | description | -| ---------------- | -------- | -------- | ------------------------------------------------------ | -| stash | string | false | Address that needs to be chilled | -| WaitForInclusion | WaitFor | false | wait for block inclusion or finalization | -| api | API | false | api for avail chain | -| Seed | Mnemonic | false | seed of the account that needs to sign the transaction | - -#### Return value - -On failure, a reason of failure is returned. On Success, transaction hash and block hash is returned. - -### Minimal Example - -```go -package main - -import ( - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/tx" - - "fmt" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - WaitFor := sdk.BlockInclusion - - stash := "5GNJqTPyNqANBkUVMN1LPPrxXnFouWXoe2wNSmmEoLctxiZY" - BlockHash, txHash, err := tx.ChillOther(api, config.Seed, WaitFor, stash) - if err != nil { - fmt.Printf("cannot submit Transaction:%v", err) - } - fmt.Printf("Transaction submitted successfully with block hash: %v\n and ext hash:%v", BlockHash.Hex(), txHash.Hex()) -} -``` - -## Nominate - -Origin Level: Signed - -### Interface - -```go -func Nominate(api *sdk.SubstrateAPI, seed string, WaitForInclusion sdk.WaitFor, stash []string) (types.Hash, types.Hash, error) -``` - -#### Parameters - -| parameter | type | optional | description | -| ---------------- | -------- | -------- | ------------------------------------------------------ | -| stash | string[] | false | list od addresses to nominate | -| WaitForInclusion | WaitFor | false | wait for block inclusion or finalization | -| api | API | false | api for avail chain | -| Seed | Mnemonic | false | seed of the account that needs to sign the transaction | - -#### Return value - -On failure, a reason of failure is returned. On Success, transaction hash and block hash is returned. - -### Minimal Example - -```go -package main - -import ( - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/tx" - - "fmt" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - WaitFor := sdk.BlockInclusion - - stash := []string{"5GNJqTPyNqANBkUVMN1LPPrxXnFouWXoe2wNSmmEoLctxiZY", "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty"} - BlockHash, txHash, err := tx.Nominate(api, config.Seed, WaitFor, stash) - if err != nil { - fmt.Printf("cannot submit Transaction:%v", err) - } - fmt.Printf("Transaction submitted successfully with block hash: %v\n and ext hash:%v", BlockHash.Hex(), txHash.Hex()) -} -``` - -## Unbond - -Origin Level: Signed - -### Interface - -```go -func Unbond(api *sdk.SubstrateAPI, seed string, WaitForInclusion sdk.WaitFor, amount types.UCompact) (types.Hash, types.Hash, error) -``` - -#### Parameters - -| parameter | type | optional | description | -| ---------------- | -------- | -------- | ------------------------------------------------------ | -| amount | Ucompact | false | amount of tokens to unbond | -| WaitForInclusion | WaitFor | false | wait for block inclusion or finalization | -| api | API | false | api for avail chain | -| Seed | Mnemonic | false | seed of the account that needs to sign the transaction | - -#### Return value - -On failure, a reason of failure is returned. On Success, Unbonded event, transaction hash and block hash is returned. - -### Minimal Example - -```go -package main - -import ( - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/tx" - "github.com/availproject/avail-go-sdk/src/sdk/types" - "math/big" - - "fmt" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - WaitFor := sdk.BlockInclusion - - bondAmount := new(big.Int) - bondAmount.SetString("100000000000000000000", 10) - - // Convert big.Int to types.UCompact - bondAmountUCompact := types.NewUCompact(bondAmount) - BlockHash, txHash, err := tx.Unbond(api, config.Seed, WaitFor, bondAmountUCompact) - if err != nil { - fmt.Printf("cannot submit Transaction:%v", err) - } - fmt.Printf("Transaction submitted successfully with block hash: %v\n and ext hash:%v", BlockHash.Hex(), txHash.Hex()) -} -``` - -## Validate - -Origin Level: Signed - -### Interface - -```go -func Validate(api *sdk.SubstrateAPI, seed string, WaitForInclusion sdk.WaitFor, commissionNum int) (types.Hash, types.Hash, error) -``` - -#### Parameters - -| parameter | type | optional | description | -| ---------------- | -------- | -------- | ------------------------------------------------------ | -| commission | number | false | how much validator charge nominators in 0 - 100 range | -| WaitForInclusion | WaitFor | false | wait for block inclusion or finalization | -| api | API | false | api for avail chain | -| Seed | Mnemonic | false | seed of the account that needs to sign the transaction | - -#### Return value - -On failure, a reason of failure is returned. On Success, transaction hash and block hash is returned. - -### Minimal Example - -```js -package main - -import ( - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/tx" - "fmt" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - WaitFor := sdk.BlockInclusion - commission := 5 - BlockHash, txHash, err := tx.Validate(api, config.Seed, WaitFor, commission) - if err != nil { - fmt.Printf("cannot submit Transaction:%v", err) - } - fmt.Printf("Transaction submitted successfully with block hash: %v\n and ext hash:%v", BlockHash.Hex(), txHash.Hex()) -} -``` diff --git a/examples/balance_allow_death/main.go b/examples/balance_allow_death/main.go deleted file mode 100644 index b6d8d69..0000000 --- a/examples/balance_allow_death/main.go +++ /dev/null @@ -1,34 +0,0 @@ -package main - -import ( - "math" - - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/tx" - "github.com/availproject/avail-go-sdk/src/sdk/types" - - "fmt" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - WaitFor := sdk.BlockInclusion - - amount := uint64(math.Pow(10, 18)) * 10 // send amount 10 AVAIL - dest := "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty" - bondAmountUCompact := types.NewUCompactFromUInt(amount) - BlockHash, txHash, err := tx.TransferAllowDeath(api, config.Seed, WaitFor, dest, bondAmountUCompact) - if err != nil { - fmt.Printf("cannot submit Transaction:%v", err) - } - fmt.Printf("Transaction submitted successfully with block hash: %v\n and ext hash:%v", BlockHash.Hex(), txHash.Hex()) - sdk.EventParser(api, BlockHash, "BalanceTransfer") -} diff --git a/examples/balance_transfer_all/main.go b/examples/balance_transfer_all/main.go deleted file mode 100644 index cdd2e3b..0000000 --- a/examples/balance_transfer_all/main.go +++ /dev/null @@ -1,28 +0,0 @@ -package main - -import ( - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/tx" - - "fmt" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - WaitFor := sdk.BlockInclusion - - dest := "5GNJqTPyNqANBkUVMN1LPPrxXnFouWXoe2wNSmmEoLctxiZY" - BlockHash, txHash, err := tx.TransferAll(api, config.Seed, WaitFor, dest) - if err != nil { - fmt.Printf("cannot submit Transaction:%v", err) - } - fmt.Printf("Transaction submitted successfully with block hash: %v\n and ext hash:%v", BlockHash.Hex(), txHash.Hex()) -} diff --git a/examples/balances_keep_alive/main.go b/examples/balances_keep_alive/main.go deleted file mode 100644 index 9caad09..0000000 --- a/examples/balances_keep_alive/main.go +++ /dev/null @@ -1,34 +0,0 @@ -package main - -import ( - "math" - - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/tx" - "github.com/availproject/avail-go-sdk/src/sdk/types" - - "fmt" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - WaitFor := sdk.BlockInclusion - - amount := uint64(math.Pow(10, 18)) * 10 // send amount 10 AVAIL - dest := "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty" - bondAmountUCompact := types.NewUCompactFromUInt(amount) - BlockHash, txHash, err := tx.TransferKeepAlive(api, config.Seed, WaitFor, dest, bondAmountUCompact) - if err != nil { - fmt.Printf("cannot submit Transaction:%v", err) - } - fmt.Printf("Transaction submitted successfully with block hash: %v\n and ext hash:%v", BlockHash.Hex(), txHash.Hex()) - sdk.EventParser(api, BlockHash, "BalanceTransfer") -} diff --git a/examples/config.json b/examples/config.json deleted file mode 100644 index 4381b4d..0000000 --- a/examples/config.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "seed": "bottom drive obey lake curtain smoke basket hold race lonely fit walk//Alice", - "api_url": "ws://127.0.0.1:9944", - "size": 1000, - "app_id": 0, - "dest": "5H3qehpRTFiB3XwyTzYU43SpG7e8jW87vFug95fxdew76Vyi", - "amount": 10 -} diff --git a/examples/connect/main.go b/examples/connect/main.go deleted file mode 100644 index d816036..0000000 --- a/examples/connect/main.go +++ /dev/null @@ -1,35 +0,0 @@ -package main - -import ( - "fmt" - - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" -) - -// The following example shows how to connect to a node and display some basic information. -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - chain, err := api.RPC.System.Chain() - if err != nil { - panic(fmt.Sprintf("cannot get chain:%v", err)) - } - name, err := api.RPC.System.Name() - if err != nil { - panic(fmt.Sprintf("cannot get name:%v", err)) - } - - version, err := api.RPC.System.Version() - if err != nil { - panic(fmt.Sprintf("cannot get version:%v", err)) - } - - fmt.Printf("Connected to chain %v using %v and node version %v\n", chain, name, version) -} diff --git a/examples/da_create_application_key/main.go b/examples/da_create_application_key/main.go deleted file mode 100644 index 168ce86..0000000 --- a/examples/da_create_application_key/main.go +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/tx" - - "fmt" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - - fmt.Println("Submitting data ...") - WaitFor := sdk.BlockInclusion - blockHash, txHash, err := tx.CreateApplicationKey(api, config.Seed, "my happyyy", WaitFor) - if err != nil { - fmt.Printf("cannot create application key:%v", err) - } - fmt.Printf("Application key created successfully with block hash: %v\n and ext hash:%v\n", blockHash.Hex(), txHash.Hex()) - sdk.EventParser(api, blockHash, "ApplicationKeyCreated") -} diff --git a/examples/da_data_submit/main.go b/examples/da_data_submit/main.go deleted file mode 100644 index 2ac9a84..0000000 --- a/examples/da_data_submit/main.go +++ /dev/null @@ -1,36 +0,0 @@ -package main - -import ( - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/tx" - - "fmt" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - - appID := 0 - - // if app id is greater than 0 then it must be created before submitting data - if config.AppID != 0 { - appID = config.AppID - } - fmt.Println("Submitting data ...") - WaitFor := sdk.BlockInclusion - - // submit data - BlockHash, txHash, err := tx.SubmitData(api, config.Seed, appID, "my happy data", WaitFor) - if err != nil { - fmt.Printf("cannot submit data:%v", err) - } - fmt.Printf("Data submitted successfully with block hash: %v\n and ext hash:%v", BlockHash.Hex(), txHash.Hex()) -} diff --git a/examples/da_data_submit_watch/main.go b/examples/da_data_submit_watch/main.go deleted file mode 100644 index d296bea..0000000 --- a/examples/da_data_submit_watch/main.go +++ /dev/null @@ -1,36 +0,0 @@ -package main - -import ( - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/tx" - - "fmt" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - - appID := 0 - - // if app id is greater than 0 then it must be created before submitting data - if config.AppID != 0 { - appID = config.AppID - } - fmt.Println("Submitting data ...") - WaitFor := sdk.BlockFinalization - // submit data - blockHash, txHash, err := tx.SubmitData(api, config.Seed, appID, "my happy data", WaitFor) - if err != nil { - fmt.Printf("cannot submit data:%v", err) - } - fmt.Printf("Data submitted successfully with block hash: %v\n and ext hash:%v\n", blockHash.Hex(), txHash.Hex()) - sdk.EventParser(api, blockHash, "DataSubmitted") -} diff --git a/examples/da_set_application_key/main.go b/examples/da_set_application_key/main.go deleted file mode 100644 index 937cecf..0000000 --- a/examples/da_set_application_key/main.go +++ /dev/null @@ -1,30 +0,0 @@ -package main - -import ( - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/tx" - - "fmt" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - fmt.Println("Submitting data ...") - WaitFor := sdk.BlockInclusion - newKey := "newKey" - oldKey := "oldKey" - blockHash, txHash, err := tx.SetApplicationKey(api, config.Seed, WaitFor, oldKey, newKey) - if err != nil { - fmt.Printf("cannot set key:%v", err) - } - fmt.Printf("Application Key updated successfully with block hash: %v\n and ext hash:%v\n", blockHash.Hex(), txHash.Hex()) - sdk.EventParser(api, blockHash, "ApplicationKeySet") -} diff --git a/examples/da_submit_block_length/main.go b/examples/da_submit_block_length/main.go deleted file mode 100644 index 7b16467..0000000 --- a/examples/da_submit_block_length/main.go +++ /dev/null @@ -1,30 +0,0 @@ -package main - -import ( - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/tx" - - "fmt" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - - fmt.Println("Submitting data ...") - WaitFor := sdk.BlockInclusion - rows := uint32(128) - cols := uint32(128) - blockHash, txHash, err := tx.SubmitBlockLength(api, config.Seed, WaitFor, rows, cols) - if err != nil { - fmt.Printf("cannot submit block length:%v", err) - } - fmt.Printf("Block Length updated successfully with block hash: %v\n and ext hash:%v\n", blockHash.Hex(), txHash.Hex()) -} diff --git a/examples/da_submit_data_fee_modifier/main.go b/examples/da_submit_data_fee_modifier/main.go deleted file mode 100644 index 9d8b84a..0000000 --- a/examples/da_submit_data_fee_modifier/main.go +++ /dev/null @@ -1,42 +0,0 @@ -package main - -import ( - "math/big" - - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/tx" - - "fmt" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - tenPow18 := new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil) - - weightMaximumFee := sdk.NewU128(tenPow18) - weightFeeDivider := sdk.NewU32(20) - weightFeeMultiplier := sdk.NewU32(1) - - // Create the DispatchFeeModifier - modifier := sdk.DispatchFeeModifier{ - WeightMaximumFee: weightMaximumFee, - WeightFeeDivider: weightFeeDivider, - WeightFeeMultiplier: weightFeeMultiplier, - } - fmt.Println("Submitting data ...") - WaitFor := sdk.BlockInclusion - blockHash, txHash, err := tx.SetSubmitDataFeeModifier(api, config.Seed, WaitFor, modifier) - if err != nil { - fmt.Printf("cannot update DA fee:%v", err) - } - fmt.Printf("Data Fee modified successfully with block hash: %v\n and ext hash:%v\n", blockHash.Hex(), txHash.Hex()) - -} diff --git a/examples/estimate-fee/main.go b/examples/estimate-fee/main.go deleted file mode 100644 index f05a610..0000000 --- a/examples/estimate-fee/main.go +++ /dev/null @@ -1,77 +0,0 @@ -package main - -import ( - "encoding/json" - "log" - "math" - "math/big" - - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/types" - "github.com/vedhavyas/go-subkey" - - "fmt" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - - amount := uint64(math.Pow(10, 18)) * 10 // send amount 10 AVAIL - dest := "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty" - keyringPair, err := sdk.KeyringFromSeed(config.Seed) - if err != nil { - panic(fmt.Sprintf("cannot create KeyPair:%v", err)) - } - _, pubkeyBytes, _ := subkey.SS58Decode(dest) - hexString := subkey.EncodeHex(pubkeyBytes) - destAddr, err := sdk.NewMultiAddressFromHexAccountID(hexString) - if err != nil { - log.Fatalf("Failed to create address from given hex: %v", err) - } - bondAmountUCompact := types.NewUCompactFromUInt(amount) - - ext, err := sdk.CreateExtrinsic(api, "Balances.transfer_keep_alive", keyringPair, 0, destAddr, bondAmountUCompact) - if err != nil { - log.Fatalf("Failed to create extrinsic: %v", err) - } - - encodedExt, err := sdk.EncodeToHex(ext) - if err != nil { - log.Fatalf("Failed to encode extrinsic: %v", err) - } - fmt.Println("Encoded Extrinsic:", encodedExt) - var paymentInfo map[string]interface{} - err = api.Client.Call(&paymentInfo, "payment_queryInfo", encodedExt, nil) - if err != nil { - log.Fatalf("Failed to get payment info: %v", err) - } - - // Format the weight - weight := paymentInfo["weight"].(map[string]interface{}) - weightJSON, err := json.Marshal(map[string]interface{}{ - "refTime": weight["ref_time"], - "proofSize": weight["proof_size"], - }) - if err != nil { - log.Fatalf("Failed to marshal weight: %v", err) - } - - // Format the partial fee - partialFee, ok := new(big.Int).SetString(paymentInfo["partialFee"].(string), 10) - if !ok { - log.Fatalf("Failed to parse partialFee") - } - mAVAIL := new(big.Float).Quo(new(big.Float).SetInt(partialFee), big.NewFloat(1e15)) - fmt.Printf("Transaction Fee for Balance Transfer:\n") - fmt.Printf(" class=%s,\n", paymentInfo["class"]) - fmt.Printf(" weight=%s,\n", string(weightJSON)) - fmt.Printf(" partialFee=%.4f mAVAIL\n", mAVAIL) -} diff --git a/examples/existential/main.go b/examples/existential/main.go deleted file mode 100644 index de10696..0000000 --- a/examples/existential/main.go +++ /dev/null @@ -1,20 +0,0 @@ -package main - -import ( - "fmt" - - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - sdk.ExistentialDeposit(api) -} diff --git a/examples/go.mod b/examples/go.mod deleted file mode 100644 index 1330bd1..0000000 --- a/examples/go.mod +++ /dev/null @@ -1,34 +0,0 @@ -module examples - -go 1.21.0 - -require ( - github.com/availproject/avail-go-sdk v0.1.2 - github.com/vedhavyas/go-subkey v1.0.4 -) - -require ( - github.com/ChainSafe/go-schnorrkel v1.0.0 // indirect - github.com/centrifuge/go-substrate-rpc-client/v4 v4.2.1 // indirect - github.com/cosmos/go-bip39 v1.0.0 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/deckarep/golang-set v1.8.0 // indirect - github.com/decred/base58 v1.0.4 // indirect - github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect - github.com/ethereum/go-ethereum v1.10.20 // indirect - github.com/go-stack/stack v1.8.1 // indirect - github.com/gorilla/websocket v1.5.0 // indirect - github.com/gtank/merlin v0.1.1 // indirect - github.com/gtank/ristretto255 v0.1.2 // indirect - github.com/mimoo/StrobeGo v0.0.0-20220103164710-9a04d6ca976b // indirect - github.com/pierrec/xxHash v0.1.5 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/rs/cors v1.8.2 // indirect - github.com/stretchr/objx v0.1.1 // indirect - github.com/stretchr/testify v1.7.2 // indirect - github.com/vedhavyas/go-subkey/v2 v2.0.0 // indirect - golang.org/x/crypto v0.22.0 // indirect - golang.org/x/sys v0.19.0 // indirect - gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect -) diff --git a/examples/go.sum b/examples/go.sum deleted file mode 100644 index 7d6322a..0000000 --- a/examples/go.sum +++ /dev/null @@ -1,87 +0,0 @@ -github.com/ChainSafe/go-schnorrkel v1.0.0 h1:3aDA67lAykLaG1y3AOjs88dMxC88PgUuHRrLeDnvGIM= -github.com/ChainSafe/go-schnorrkel v1.0.0/go.mod h1:dpzHYVxLZcp8pjlV+O+UR8K0Hp/z7vcchBSbMBEhCw4= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= -github.com/availproject/avail-go-sdk v0.1.2 h1:DZLuEFmLlMHyqRcAaIkJumiMTMYVBqEWXDemSuCF4Xo= -github.com/availproject/avail-go-sdk v0.1.2/go.mod h1:2LX1D4jRJhLAozmUF8Fzrh8FUA0WhjT1VpUykZsUqDM= -github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo= -github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k= -github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= -github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce h1:YtWJF7RHm2pYCvA5t0RPmAaLUhREsKuKd+SLhxFbFeQ= -github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= -github.com/centrifuge/go-substrate-rpc-client/v4 v4.2.1 h1:io49TJ8IOIlzipioJc9pJlrjgdJvqktpUWYxVY5AUjE= -github.com/centrifuge/go-substrate-rpc-client/v4 v4.2.1/go.mod h1:k61SBXqYmnZO4frAJyH3iuqjolYrYsq79r8EstmklDY= -github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= -github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= -github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4= -github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= -github.com/decred/base58 v1.0.4 h1:QJC6B0E0rXOPA8U/kw2rP+qiRJsUaE2Er+pYb3siUeA= -github.com/decred/base58 v1.0.4/go.mod h1:jJswKPEdvpFpvf7dsDvFZyLT22xZ9lWqEByX38oGd9E= -github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= -github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= -github.com/ethereum/go-ethereum v1.10.20 h1:75IW830ClSS40yrQC1ZCMZCt5I+zU16oqId2SiQwdQ4= -github.com/ethereum/go-ethereum v1.10.20/go.mod h1:LWUN82TCHGpxB3En5HVmLLzPD7YSrEUFmFfN1nKkVN0= -github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= -github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= -github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= -github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= -github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa h1:Q75Upo5UN4JbPFURXZ8nLKYUvF85dyFRop/vQ0Rv+64= -github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= -github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is= -github.com/gtank/merlin v0.1.1/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= -github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc= -github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o= -github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= -github.com/mimoo/StrobeGo v0.0.0-20220103164710-9a04d6ca976b h1:QrHweqAtyJ9EwCaGHBu1fghwxIPiopAHV06JlXrMHjk= -github.com/mimoo/StrobeGo v0.0.0-20220103164710-9a04d6ca976b/go.mod h1:xxLb2ip6sSUts3g1irPVHyk/DGslwQsNOo9I7smJfNU= -github.com/pierrec/xxHash v0.1.5 h1:n/jBpwTHiER4xYvK3/CdPVnLDPchj8eTJFFLUb4QHBo= -github.com/pierrec/xxHash v0.1.5/go.mod h1:w2waW5Zoa/Wc4Yqe0wgrIYAGKqRMf7czn2HNKXmuL+I= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= -github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= -github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= -github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= -github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= -github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= -github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= -github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= -github.com/vedhavyas/go-subkey v1.0.4 h1:QwjBZx4w7qXC2lmqol2jJfhaNXPI9BsgLZiMiCwqGDU= -github.com/vedhavyas/go-subkey v1.0.4/go.mod h1:aOIil/KS9hJlnr9ZSQKSoXdu/MbnkCxG4x9IOlLsMtI= -github.com/vedhavyas/go-subkey/v2 v2.0.0 h1:LemDIsrVtRSOkp0FA8HxP6ynfKjeOj3BY2U9UNfeDMA= -github.com/vedhavyas/go-subkey/v2 v2.0.0/go.mod h1:95aZ+XDCWAUUynjlmi7BtPExjXgXxByE0WfBwbmIRH4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= -golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= -gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/examples/listenNewBlocks/main.go b/examples/listenNewBlocks/main.go deleted file mode 100644 index 8fac06d..0000000 --- a/examples/listenNewBlocks/main.go +++ /dev/null @@ -1,38 +0,0 @@ -package main - -import ( - "fmt" - - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" -) - -// The following example shows how to connect to a node and listen for a new blocks -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - - subscription, err := api.RPC.Chain.SubscribeNewHeads() - if err != nil { - panic(fmt.Sprintf("cannot subscribe:%v", err)) - } - - // number of blocks to wait - waitForBlocks := 5 - count := 0 - for i := range subscription.Chan() { - count++ - fmt.Printf("Chain is at block: #%v\n", i.Number) - if count == waitForBlocks { - break - } - } - - subscription.Unsubscribe() -} diff --git a/examples/properties/main.go b/examples/properties/main.go deleted file mode 100644 index eac47d1..0000000 --- a/examples/properties/main.go +++ /dev/null @@ -1,31 +0,0 @@ -package main - -import ( - "fmt" - - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/types" -) - -func main() { - - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - - var properties types.ChainProperties - err = api.Client.Call(&properties, "system_properties", nil) - - if err != nil { - panic(fmt.Sprintf("cannot get properties:%v", err)) - } - - fmt.Printf("\nChain properties:TokenSymbol:%#v\nTokenDecimals:%d\nSS58Format:%d\n", properties.TokenSymbol, properties.TokenDecimals, properties.SS58Format) - -} diff --git a/examples/rpc/author_rotate/main.go b/examples/rpc/author_rotate/main.go deleted file mode 100644 index b8f584b..0000000 --- a/examples/rpc/author_rotate/main.go +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "fmt" - "log" - - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/call" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - if api == nil || api.Client == nil { - log.Fatal("API client is not properly initialized") - } - resp, err := call.Author_Rotate(api) - if err != nil { - fmt.Printf("cannot author rotate:%v", err) - } - fmt.Printf("New session keys: 0x%x\n", resp) -} diff --git a/examples/rpc/chain_finalizedHead/main.go b/examples/rpc/chain_finalizedHead/main.go deleted file mode 100644 index c1286a9..0000000 --- a/examples/rpc/chain_finalizedHead/main.go +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "fmt" - "log" - - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/rpc" - "github.com/availproject/avail-go-sdk/src/sdk" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - if api == nil || api.Client == nil { - log.Fatal("API client is not properly initialized") - } - resp, err := rpc.GetFinalizedHead(api.Client) - if err != nil { - fmt.Printf("cannot call finalized header RPC:%v", err) - } - fmt.Println(resp.Hex()) -} diff --git a/examples/rpc/chain_getBlock/main.go b/examples/rpc/chain_getBlock/main.go deleted file mode 100644 index 229f19e..0000000 --- a/examples/rpc/chain_getBlock/main.go +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "fmt" - "log" - - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/rpc" - "github.com/availproject/avail-go-sdk/src/sdk" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - if api == nil || api.Client == nil { - log.Fatal("API client is not properly initialized") - } - resp, err := rpc.GetAvailBlockLatest(api.Client) - if err != nil { - fmt.Printf("cannot author rotate:%v", err) - } - fmt.Println(resp) -} diff --git a/examples/rpc/chain_getBlockHash/main.go b/examples/rpc/chain_getBlockHash/main.go deleted file mode 100644 index 7c13e88..0000000 --- a/examples/rpc/chain_getBlockHash/main.go +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "fmt" - "log" - - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/rpc" - "github.com/availproject/avail-go-sdk/src/sdk" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - if api == nil || api.Client == nil { - log.Fatal("API client is not properly initialized") - } - resp, err := rpc.GetBlockHashLatest(api.Client) - if err != nil { - fmt.Printf("cannot call latest block hash RPC:%v", err) - } - fmt.Println(resp.Hex()) -} diff --git a/examples/rpc/chain_getHeader/main.go b/examples/rpc/chain_getHeader/main.go deleted file mode 100644 index 3e99605..0000000 --- a/examples/rpc/chain_getHeader/main.go +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "fmt" - "log" - - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/rpc" - "github.com/availproject/avail-go-sdk/src/sdk" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - if api == nil || api.Client == nil { - log.Fatal("API client is not properly initialized") - } - resp, err := rpc.GetHeaderLatest(api.Client) - if err != nil { - fmt.Printf("cannot call latest header RPC:%v", err) - } - fmt.Println(resp) -} diff --git a/examples/rpc/kate_queryProof/main.go b/examples/rpc/kate_queryProof/main.go deleted file mode 100644 index fb4c735..0000000 --- a/examples/rpc/kate_queryProof/main.go +++ /dev/null @@ -1,54 +0,0 @@ -package main - -import ( - "encoding/json" - "fmt" - "log" - - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/rpc" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/call" - "github.com/availproject/avail-go-sdk/src/sdk/tx" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - if api == nil || api.Client == nil { - log.Fatal("API client is not properly initialized") - } - - appID := 0 - - // if app id is greater than 0 then it must be created before submitting data - if config.AppID != 0 { - appID = config.AppID - } - WaitFor := sdk.BlockFinalization - - blockHash, txHash, err := tx.SubmitData(api, config.Seed, appID, "my happy data", WaitFor) - if err != nil { - fmt.Printf("cannot submit data:%v", err) - } - fmt.Printf("Data submitted successfully with block hash: %v\n and ext hash:%v\n", blockHash.Hex(), txHash.Hex()) - testCell := []rpc.Cell{rpc.NewCell(0, 0), rpc.NewCell(0, 1)} - result, err := call.Query_proof(api, testCell, blockHash) - if err != nil { - fmt.Printf("cannot query proof:%v", err) - } - - resultJSON, err := json.Marshal(result) - if err != nil { - fmt.Println("Error marshalling result to JSON:", err) - return - } - - fmt.Println(string(resultJSON)) -} diff --git a/examples/rpc/kate_queryProofData/main.go b/examples/rpc/kate_queryProofData/main.go deleted file mode 100644 index 27d0de2..0000000 --- a/examples/rpc/kate_queryProofData/main.go +++ /dev/null @@ -1,74 +0,0 @@ -package main - -import ( - "fmt" - "log" - - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/rpc" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/call" - "github.com/availproject/avail-go-sdk/src/sdk/tx" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - if api == nil || api.Client == nil { - log.Fatal("API client is not properly initialized") - } - - appID := 0 - - // if app id is greater than 0 then it must be created before submitting data - if config.AppID != 0 { - appID = config.AppID - } - WaitFor := sdk.BlockFinalization - - blockHash, _, err := tx.SubmitData(api, config.Seed, appID, "my happy data", WaitFor) - if err != nil { - fmt.Printf("cannot submit data:%v", err) - } - fmt.Printf("Transaction included in finalized block: %v\n", blockHash.Hex()) - - transactionIndex := sdk.NewU32(1) - - // query proof - response, err := call.Query_dataproof(api, transactionIndex, blockHash) - if err != nil { - fmt.Printf("cannot query proof:%v", err) - } - fmt.Printf("DataRoot:%v\n", response.DataProof.Roots.DataRoot.Hex()) - fmt.Printf("BlobRoot:%v\n", response.DataProof.Roots.BlobRoot.Hex()) - fmt.Printf("BridgeRoot:%v\n", response.DataProof.Roots.BridgeRoot.Hex()) - // print array of proof - fmt.Printf("Proof:\n") - for _, p := range response.DataProof.Proof { - fmt.Printf("%v\n", p.Hex()) - } - - fmt.Printf("Number of leaves: %v\n", response.DataProof.NumberOfLeaves) - fmt.Printf("Leaf index: %v\n", response.DataProof.LeafIndex) - fmt.Printf("Leaf: %v\n", response.DataProof.Leaf.Hex()) - - // Access the message based on its type - if response.Message != nil { - switch m := response.Message.(type) { - case *rpc.ArbitraryMessage: - fmt.Println("Arbitrary Message:", m.BoundedData) - case *rpc.FungibleToken: - fmt.Println("Fungible Token AssetID:", m.AssetID.Hex(), "Amount:", m.Amount) - default: - fmt.Println("Unknown Message Type") - } - } else { - fmt.Println("Message: null") - } -} diff --git a/examples/rpc/kate_queryRows/main.go b/examples/rpc/kate_queryRows/main.go deleted file mode 100644 index f662924..0000000 --- a/examples/rpc/kate_queryRows/main.go +++ /dev/null @@ -1,59 +0,0 @@ -package main - -import ( - "fmt" - - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/call" - "github.com/availproject/avail-go-sdk/src/sdk/tx" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - - appID := 0 - - // if app id is greater than 0 then it must be created before submitting data - if config.AppID != 0 { - appID = config.AppID - } - WaitFor := sdk.BlockFinalization - - blockHash, txHash, err := tx.SubmitData(api, config.Seed, appID, "my happy data", WaitFor) - if err != nil { - fmt.Printf("cannot submit data:%v", err) - } - fmt.Printf("Data submitted successfully with block hash: %v\n and ext hash:%v\n", blockHash.Hex(), txHash.Hex()) - - defer func() { - if r := recover(); r != nil { - fmt.Println("Recovered in main", r) - } - }() - myArr := make([]uint32, 1) - myArr[0] = 0 - response, err := call.Query_rows(api, myArr, blockHash) - if err != nil { - fmt.Println("Error calling api.Client.Call:", err) - return - } - - formattedResponse := make([][]string, len(response)) - - for i, innerSlice := range response { - formattedResponse[i] = make([]string, len(innerSlice)) - for j, num := range innerSlice { - formattedResponse[i][j] = sdk.FormatBN(num) - } - } - fmt.Println(formattedResponse) - -} diff --git a/examples/staking_bond/main.go b/examples/staking_bond/main.go deleted file mode 100644 index 648f1c8..0000000 --- a/examples/staking_bond/main.go +++ /dev/null @@ -1,31 +0,0 @@ -package main - -import ( - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/tx" - - "fmt" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - WaitFor := sdk.BlockInclusion - Payee := sdk.Staked - - bondAmount := int64(1000) - - BlockHash, txHash, err := tx.Bond(api, config.Seed, WaitFor, bondAmount, sdk.Payee(Payee)) - if err != nil { - fmt.Printf("cannot submit Transaction:%v", err) - } - fmt.Printf("Transaction submitted successfully with block hash: %v\n and ext hash:%v", BlockHash.Hex(), txHash.Hex()) - sdk.EventParser(api, BlockHash, "Bond") -} diff --git a/examples/staking_bond_extra/main.go b/examples/staking_bond_extra/main.go deleted file mode 100644 index 7cc0796..0000000 --- a/examples/staking_bond_extra/main.go +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/tx" - - "fmt" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - WaitFor := sdk.BlockInclusion - - bondAmount := int64(1000) - - BlockHash, txHash, err := tx.BondExtra(api, config.Seed, WaitFor, bondAmount) - if err != nil { - fmt.Printf("cannot submit Transaction:%v", err) - } - fmt.Printf("Transaction submitted successfully with block hash: %v\n and ext hash:%v", BlockHash.Hex(), txHash.Hex()) -} diff --git a/examples/staking_chill/main.go b/examples/staking_chill/main.go deleted file mode 100644 index a426869..0000000 --- a/examples/staking_chill/main.go +++ /dev/null @@ -1,27 +0,0 @@ -package main - -import ( - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/tx" - - "fmt" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - WaitFor := sdk.BlockInclusion - - BlockHash, txHash, err := tx.Chill(api, config.Seed, WaitFor) - if err != nil { - fmt.Printf("cannot submit Transaction:%v", err) - } - fmt.Printf("Transaction submitted successfully with block hash: %v\n and ext hash:%v", BlockHash.Hex(), txHash.Hex()) -} diff --git a/examples/staking_chill_other/main.go b/examples/staking_chill_other/main.go deleted file mode 100644 index 45b60ff..0000000 --- a/examples/staking_chill_other/main.go +++ /dev/null @@ -1,28 +0,0 @@ -package main - -import ( - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/tx" - - "fmt" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - WaitFor := sdk.BlockInclusion - - stash := "5GNJqTPyNqANBkUVMN1LPPrxXnFouWXoe2wNSmmEoLctxiZY" - BlockHash, txHash, err := tx.ChillOther(api, config.Seed, WaitFor, stash) - if err != nil { - fmt.Printf("cannot submit data:%v", err) - } - fmt.Printf("Transaction submitted successfully with block hash: %v\n and ext hash:%v", BlockHash.Hex(), txHash.Hex()) -} diff --git a/examples/staking_nominate/main.go b/examples/staking_nominate/main.go deleted file mode 100644 index 6aae380..0000000 --- a/examples/staking_nominate/main.go +++ /dev/null @@ -1,28 +0,0 @@ -package main - -import ( - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/tx" - - "fmt" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - WaitFor := sdk.BlockInclusion - - stash := []string{"5GNJqTPyNqANBkUVMN1LPPrxXnFouWXoe2wNSmmEoLctxiZY", "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty"} - BlockHash, txHash, err := tx.Nominate(api, config.Seed, WaitFor, stash) - if err != nil { - fmt.Printf("cannot submit Transaction:%v", err) - } - fmt.Printf("Transaction submitted successfully with block hash: %v\n and ext hash:%v", BlockHash.Hex(), txHash.Hex()) -} diff --git a/examples/staking_unbond/main.go b/examples/staking_unbond/main.go deleted file mode 100644 index abbb9bd..0000000 --- a/examples/staking_unbond/main.go +++ /dev/null @@ -1,35 +0,0 @@ -package main - -import ( - "math/big" - - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/tx" - "github.com/availproject/avail-go-sdk/src/sdk/types" - - "fmt" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - WaitFor := sdk.BlockInclusion - - bondAmount := new(big.Int) - bondAmount.SetString("100000000000000000000", 10) - - // Convert big.Int to types.UCompact - bondAmountUCompact := types.NewUCompact(bondAmount) - BlockHash, txHash, err := tx.Unbond(api, config.Seed, WaitFor, bondAmountUCompact) - if err != nil { - fmt.Printf("cannot submit Transaction:%v", err) - } - fmt.Printf("Transaction submitted successfully with block hash: %v\n and ext hash:%v", BlockHash.Hex(), txHash.Hex()) -} diff --git a/examples/staking_validate/main.go b/examples/staking_validate/main.go deleted file mode 100644 index acdecb8..0000000 --- a/examples/staking_validate/main.go +++ /dev/null @@ -1,28 +0,0 @@ -package main - -import ( - "fmt" - - "github.com/availproject/avail-go-sdk/src/config" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/tx" -) - -func main() { - config, err := config.LoadConfig() - if err != nil { - fmt.Printf("cannot load config:%v", err) - } - api, err := sdk.NewSDK(config.ApiURL) - if err != nil { - fmt.Printf("cannot create api:%v", err) - } - WaitFor := sdk.BlockInclusion - commission := 5 - BlockHash, txHash, err := tx.Validate(api, config.Seed, WaitFor, commission) - if err != nil { - fmt.Printf("cannot submit Transaction:%v", err) - } - fmt.Printf("Transaction submitted successfully with block hash: %v\n and ext hash:%v", BlockHash.Hex(), txHash.Hex()) - -} diff --git a/go.mod b/go.mod index 082ddce..5e66432 100644 --- a/go.mod +++ b/go.mod @@ -1,35 +1,30 @@ -module github.com/availproject/avail-go-sdk +module go-sdk -go 1.21.0 +go 1.23.4 require ( github.com/centrifuge/go-substrate-rpc-client/v4 v4.2.1 - github.com/ethereum/go-ethereum v1.10.20 - github.com/vedhavyas/go-subkey v1.0.4 + github.com/itering/scale.go v1.9.14 github.com/vedhavyas/go-subkey/v2 v2.0.0 - golang.org/x/crypto v0.7.0 + golang.org/x/crypto v0.31.0 ) require ( github.com/ChainSafe/go-schnorrkel v1.0.0 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect github.com/deckarep/golang-set v1.8.0 // indirect github.com/decred/base58 v1.0.4 // indirect github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect + github.com/ethereum/go-ethereum v1.10.20 // indirect github.com/go-stack/stack v1.8.1 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/gtank/merlin v0.1.1 // indirect github.com/gtank/ristretto255 v0.1.2 // indirect + github.com/huandu/xstrings v1.3.1 // indirect github.com/mimoo/StrobeGo v0.0.0-20220103164710-9a04d6ca976b // indirect github.com/pierrec/xxHash v0.1.5 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rs/cors v1.8.2 // indirect - github.com/stretchr/objx v0.1.1 // indirect - github.com/stretchr/testify v1.7.2 // indirect - golang.org/x/sys v0.6.0 // indirect + github.com/shopspring/decimal v1.2.0 // indirect + golang.org/x/sys v0.28.0 // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect ) - -// replace github.com/centrifuge/go-substrate-rpc-client/v4 => /Users/kailaskr/gsrpc diff --git a/go.sum b/go.sum index d5460e8..e2f6d58 100644 --- a/go.sum +++ b/go.sum @@ -2,7 +2,6 @@ github.com/ChainSafe/go-schnorrkel v1.0.0 h1:3aDA67lAykLaG1y3AOjs88dMxC88PgUuHRr github.com/ChainSafe/go-schnorrkel v1.0.0/go.mod h1:dpzHYVxLZcp8pjlV+O+UR8K0Hp/z7vcchBSbMBEhCw4= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= -github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo= github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k= github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce h1:YtWJF7RHm2pYCvA5t0RPmAaLUhREsKuKd+SLhxFbFeQ= @@ -38,6 +37,10 @@ github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is= github.com/gtank/merlin v0.1.1/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc= github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o= +github.com/huandu/xstrings v1.3.1 h1:4jgBlKK6tLKFvO8u5pmYjG91cqytmDCDvGh7ECVFfFs= +github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/itering/scale.go v1.9.14 h1:bWbBatYNoXfUKa0meltaThnHkFkBPn+6n48E1hGWJl4= +github.com/itering/scale.go v1.9.14/go.mod h1:J+K1ncBsW/F9lAA4ZiIDi0w8323GDS+0F7kbJ5jNq14= github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= github.com/mimoo/StrobeGo v0.0.0-20220103164710-9a04d6ca976b h1:QrHweqAtyJ9EwCaGHBu1fghwxIPiopAHV06JlXrMHjk= github.com/mimoo/StrobeGo v0.0.0-20220103164710-9a04d6ca976b/go.mod h1:xxLb2ip6sSUts3g1irPVHyk/DGslwQsNOo9I7smJfNU= @@ -49,9 +52,9 @@ github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= @@ -60,22 +63,19 @@ github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= -github.com/vedhavyas/go-subkey v1.0.4 h1:QwjBZx4w7qXC2lmqol2jJfhaNXPI9BsgLZiMiCwqGDU= -github.com/vedhavyas/go-subkey v1.0.4/go.mod h1:aOIil/KS9hJlnr9ZSQKSoXdu/MbnkCxG4x9IOlLsMtI= github.com/vedhavyas/go-subkey/v2 v2.0.0 h1:LemDIsrVtRSOkp0FA8HxP6ynfKjeOj3BY2U9UNfeDMA= github.com/vedhavyas/go-subkey/v2 v2.0.0/go.mod h1:95aZ+XDCWAUUynjlmi7BtPExjXgXxByE0WfBwbmIRH4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= -golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= diff --git a/interfaces/mod.go b/interfaces/mod.go new file mode 100644 index 0000000..b4554fb --- /dev/null +++ b/interfaces/mod.go @@ -0,0 +1,16 @@ +package interfaces + +import ( + "go-sdk/primitives" +) + +type CallDataT interface { + Decode(call primitives.Call) primitives.Option[interface{}] +} + +type EventT interface { + PalletIndex() uint8 + PalletName() string + EventIndex() uint8 + EventName() string +} diff --git a/justfile b/justfile new file mode 100644 index 0000000..60ae718 --- /dev/null +++ b/justfile @@ -0,0 +1,11 @@ +run: + go run . +build: + go build . +check: + just build +fmt: + go fmt . +test: + ./run_tests.sh + diff --git a/main.go b/main.go new file mode 100644 index 0000000..78a2135 --- /dev/null +++ b/main.go @@ -0,0 +1,80 @@ +package main + +import ( + // Complex "go-sdk/complex" + // "go-sdk/metadata" + // Balances "go-sdk/metadata/pallets/balances" + "go-sdk/complex" + "go-sdk/primitives" + "sync" + "time" + // "github.com/vedhavyas/go-subkey/v2" + // "github.com/vedhavyas/go-subkey/v2/sr25519" +) + +func Job(targetBlockNumber uint32, wg *sync.WaitGroup) { + sdk := NewSDK2("https://mainnet-rpc.avail.so/rpc") + targetBlockHash := sdk.Client.Rpc.Chain.GetBlockHash(primitives.NewSome(targetBlockNumber)) + println("Block Number:", targetBlockNumber, "Block Hash: ", targetBlockHash.ToHexWith0x()) + + targetBlockHash2 := targetBlockHash + /* + Turing + if targetBlockNumber == 297282 { + targetBlockHash2 = sdk.Client.Rpc.Chain.GetBlockHash(primitives.NewSome(targetBlockNumber - 1)) + } + */ + if err := sdk.Client.InitMetadata(primitives.NewSome(targetBlockHash2)); err != nil { + panic(err) + } + + // Decoding Extrinsics and Events + complex.NewBlock(sdk.Client, targetBlockHash) + wg.Done() +} + +func main() { + sdk := NewSDK2("https://mainnet-rpc.avail.so/rpc") + println("Genesis: ", sdk.Client.Rpc.Chain.GetBlockHash(primitives.NewSome(uint32(0))).ToHexWith0x()) + + targetBlockNumber := uint32(246585) + var wg sync.WaitGroup + for { + for i := 1; i <= 100; i++ { + wg.Add(1) + go Job(targetBlockNumber, &wg) + targetBlockNumber += 1 + } + + wg.Wait() + time.Sleep(time.Millisecond * 50) + } + + /* + // Go through blocks and see which one is not decodable + + add, err := metadata.NewAccountIdFromAddress("5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY") + if err != nil { + panic(err) + } + println(add.ToHuman()) + + uri := "bottom drive obey lake curtain smoke basket hold race lonely fit walk//Alice" + scheme := new(sr25519.Scheme) + account, _ := subkey.DeriveKeyPair(scheme, uri) + + var tx = sdk.Tx.DataAvailability.SubmitData([]byte("aabbcc")) + var options = Complex.NewTransactionOptions().WithAppId(uint32(1)) + + var details = tx.ExecuteAndWatch(account, false, options) + println("Block Hash: ", details.BlockHash.ToHexWith0x()) + println("Block Number: ", details.BlockNumber) + println("TX Events ", len(details.Events.Unwrap())) + + var eves = details.Events.Unwrap() + + var res = Complex.FindFirst(eves, Balances.EventWithdraw{}) + println("Who:", res.Unwrap().Who.ToHuman()) + println("Amount: ", res.Unwrap().Amount.ToHuman()) + */ +} diff --git a/metadata/README.md b/metadata/README.md new file mode 100644 index 0000000..181bd66 --- /dev/null +++ b/metadata/README.md @@ -0,0 +1,6 @@ +AccountIdLookupOf -> primitives.MultiAddress +Balances -> Balance +T::Balance -> Balance +AppId -> uint32 +Option -> primitives.ScaleOption +T::AccountId -> AccountId diff --git a/metadata/metadata.go b/metadata/metadata.go new file mode 100644 index 0000000..c2d6f23 --- /dev/null +++ b/metadata/metadata.go @@ -0,0 +1,354 @@ +package metadata + +import ( + "bytes" + "errors" + "fmt" + "go-sdk/primitives" + + gsrpcScale "github.com/centrifuge/go-substrate-rpc-client/v4/scale" + gsrpcTypes "github.com/centrifuge/go-substrate-rpc-client/v4/types" + "github.com/itering/scale.go/utiles/uint128" +) + +type Metadata struct { + Value gsrpcTypes.Metadata +} + +func NewMetadata(rawMetadata string) (Metadata, error) { + scaleMetadata := primitives.FromHex(rawMetadata) + + metadata := Metadata{} + if err := gsrpcScale.NewDecoder(bytes.NewReader(scaleMetadata)).Decode(&metadata.Value); err != nil { + return Metadata{}, err + } + + return metadata, nil +} + +func (this *Metadata) PalletCallName(palletIndex uint8, callIndex uint8) ([]string, error) { + pallet := this.FindPalletMetadata(palletIndex) + if pallet == nil { + return []string{}, errors.New("Metadata Failure. Failed to find Pallet") + } + v14 := this.Value.AsMetadataV14 + + if !pallet.HasEvents { + return []string{}, errors.New("Metadata Failure. Pallet has no events") + } + + callId := pallet.Calls.Type.Int64() + if typ, ok := v14.EfficientLookup[callId]; ok { + if len(typ.Def.Variant.Variants) > 0 { + for _, vars := range typ.Def.Variant.Variants { + if uint8(vars.Index) != callIndex { + continue + } + names := []string{string(pallet.Name), string(vars.Name)} + return names, nil + } + } + } + + return []string{}, errors.New(fmt.Sprintf(`Metadata Failure. Failed to find pallet and event names. Pallet Index: %v, Call Index: %v`, palletIndex, callIndex)) +} + +func (this *Metadata) PalletEventName(palletIndex uint8, eventIndex uint8) ([]string, error) { + pallet := this.FindPalletMetadata(palletIndex) + if pallet == nil { + return []string{}, errors.New("Metadata Failure. Failed to find Pallet") + } + v14 := this.Value.AsMetadataV14 + + if !pallet.HasEvents { + return []string{}, errors.New("Metadata Failure. Pallet has no events") + } + + callId := pallet.Events.Type.Int64() + if typ, ok := v14.EfficientLookup[callId]; ok { + if len(typ.Def.Variant.Variants) > 0 { + for _, vars := range typ.Def.Variant.Variants { + if uint8(vars.Index) != eventIndex { + continue + } + names := []string{string(pallet.Name), string(vars.Name)} + return names, nil + } + } + } + + return []string{}, errors.New(fmt.Sprintf(`Metadata Failure. Failed to find pallet and event names. Pallet Index: %v, Event Index: %v`, palletIndex, eventIndex)) +} + +func (this *Metadata) FindPalletMetadata(palletIndex uint8) *gsrpcTypes.PalletMetadataV14 { + v14 := this.Value.AsMetadataV14 + for _, pallet := range v14.Pallets { + if uint8(pallet.Index) == palletIndex { + return &pallet + } + } + + return nil +} + +func (this *Metadata) DecodeEvent(palletIndex uint8, eventIndex uint8, decoder *primitives.Decoder) error { + v14 := this.Value.AsMetadataV14 + pallet := this.FindPalletMetadata(palletIndex) + if pallet == nil { + return errors.New("Metadata Failure. Failed to find Pallet") + } + + if !pallet.HasEvents { + return errors.New("Metadata Failure. Pallet has no events") + } + + callId := pallet.Events.Type.Int64() + if typ, ok := v14.EfficientLookup[callId]; ok { + if len(typ.Def.Variant.Variants) == 0 { + return nil + } + + for _, vars := range typ.Def.Variant.Variants { + if uint8(vars.Index) != uint8(eventIndex) { + continue + } + for _, field := range vars.Fields { + if typ, ok1 := v14.EfficientLookup[field.Type.Int64()]; ok1 { + this.decodeMetadataValue(decoder, typ, false) + } + } + } + } else { + return errors.New(fmt.Sprintf(`Metadata Failure. No Type was found for the following id: %v`, callId)) + } + + return nil +} + +func (this *Metadata) GetTypeFromId(id int64) *gsrpcTypes.Si1Type { + v14 := this.Value.AsMetadataV14 + + if typ, ok1 := v14.EfficientLookup[id]; ok1 { + return typ + } + + return nil +} + +func (this *Metadata) decodeMetadataValue(decoder *primitives.Decoder, value *gsrpcTypes.Si1Type, isCompact bool) error { + v14 := this.Value.AsMetadataV14 + + /* path := "" + for _, str := range value.Path { + path += string(str) + " " + } + if path != "" { + println(path) + } */ + + if value.Def.IsPrimitive { + return DecodePrimitive(decoder, &value.Def.Primitive, isCompact) + } + + if value.Def.IsArray { + arr := value.Def.Array + for i := 0; i < int(arr.Len); i++ { + callId := value.Def.Array.Type.Int64() + if typ, ok := v14.EfficientLookup[callId]; ok { + if err := this.decodeMetadataValue(decoder, typ, isCompact); err != nil { + return err + } + } else { + return errors.New(fmt.Sprintf(`Metadata failure. Failed to find type with id: %v`, callId)) + } + } + + return nil + } + + if value.Def.IsTuple { + tuple := value.Def.Tuple + for _, elem := range tuple { + callId := elem.Int64() + if typ, ok := v14.EfficientLookup[callId]; ok { + this.decodeMetadataValue(decoder, typ, isCompact) + } else { + return errors.New(fmt.Sprintf(`Metadata failure. Failed to find type with id: %v`, callId)) + } + } + + return nil + } + + if value.Def.IsSequence { + len := primitives.CompactU32{} + if err := decoder.Decode(&len); err != nil { + return err + } + + seq := value.Def.Sequence + callId := seq.Type.Int64() + for i := 0; i < int(len.Value); i++ { + if typ, ok := v14.EfficientLookup[callId]; ok { + if err := this.decodeMetadataValue(decoder, typ, isCompact); err != nil { + return err + } + } else { + return errors.New(fmt.Sprintf(`Metadata failure. Failed to find type with id: %v`, callId)) + } + } + + return nil + } + + if value.Def.IsCompact { + callId := value.Def.Compact.Type.Int64() + if typ, ok := v14.EfficientLookup[callId]; ok { + if err := this.decodeMetadataValue(decoder, typ, true); err != nil { + return err + } + } else { + return errors.New(fmt.Sprintf(`Metadata failure. Failed to find type with id: %v`, callId)) + } + + return nil + } + + if value.Def.IsComposite { + com := value.Def.Composite + for _, field := range com.Fields { + callId := field.Type.Int64() + //println("Filed Name: ", string(field.Name)) + if typ, ok := v14.EfficientLookup[callId]; ok { + if err := this.decodeMetadataValue(decoder, typ, isCompact); err != nil { + return err + } + } else { + return errors.New(fmt.Sprintf(`Metadata failure. Failed to find type with id: %v`, callId)) + } + } + + return nil + } + + if value.Def.IsVariant { + defVariant := value.Def.Variant + index := uint8(0) + if err := decoder.Decode(&index); err != nil { + return err + } + + found := false + for _, variant := range defVariant.Variants { + if uint8(variant.Index) != index { + continue + } + found = true + + for _, field := range variant.Fields { + callId := field.Type.Int64() + if typ, ok := v14.EfficientLookup[callId]; ok { + if err := this.decodeMetadataValue(decoder, typ, isCompact); err != nil { + return err + } + } else { + return errors.New(fmt.Sprintf(`Metadata failure. Failed to find type with id: %v`, callId)) + } + } + } + + if !found { + return errors.New(fmt.Sprintf(`Metadata failure. Failed to find variant id %v`, index)) + } + + return nil + } + + return errors.New(fmt.Sprintf(`Metadata failure. Don't know to how decode this type.`)) +} + +func DecodePrimitive(decoder *primitives.Decoder, value *gsrpcTypes.Si1TypeDefPrimitive, isCompact bool) error { + if !isCompact { + if int(value.Si0TypeDefPrimitive) == gsrpcTypes.IsBool { + res := false + if err := decoder.Decode(&res); err != nil { + return err + } + return nil + } + + if int(value.Si0TypeDefPrimitive) == gsrpcTypes.IsU8 { + res := uint8(0) + if err := decoder.Decode(&res); err != nil { + return err + } + return nil + } + + if int(value.Si0TypeDefPrimitive) == gsrpcTypes.IsU16 { + res := uint16(0) + if err := decoder.Decode(&res); err != nil { + return err + } + return nil + } + + if int(value.Si0TypeDefPrimitive) == gsrpcTypes.IsU32 { + res := uint32(0) + if err := decoder.Decode(&res); err != nil { + return err + } + return nil + } + + if int(value.Si0TypeDefPrimitive) == gsrpcTypes.IsU64 { + res := uint64(0) + if err := decoder.Decode(&res); err != nil { + return err + } + return nil + } + + if int(value.Si0TypeDefPrimitive) == gsrpcTypes.IsU128 { + res := uint128.Uint128{} + if err := decoder.Decode(&res); err != nil { + return err + } + return nil + } + + if int(value.Si0TypeDefPrimitive) == gsrpcTypes.IsStr { + res := "" + if err := decoder.Decode(&res); err != nil { + return err + } + return nil + } + } else { + if int(value.Si0TypeDefPrimitive) == gsrpcTypes.IsU32 { + res := primitives.CompactU32{} + if err := decoder.Decode(&res); err != nil { + return err + } + return nil + } + + if int(value.Si0TypeDefPrimitive) == gsrpcTypes.IsU64 { + res := primitives.CompactU64{} + if err := decoder.Decode(&res); err != nil { + return err + } + return nil + } + + if int(value.Si0TypeDefPrimitive) == gsrpcTypes.IsU128 { + res := primitives.CompactU128{} + if err := decoder.Decode(&res); err != nil { + return err + } + return nil + } + } + + return errors.New(fmt.Sprintf(`Metadata failure. Unknown primitive type: %v`, value.Si0TypeDefPrimitive)) +} diff --git a/metadata/pallets/balances/calls.go b/metadata/pallets/balances/calls.go new file mode 100644 index 0000000..d2e5dc0 --- /dev/null +++ b/metadata/pallets/balances/calls.go @@ -0,0 +1,194 @@ +package balances + +import ( + "go-sdk/metadata" + prim "go-sdk/primitives" + + "github.com/itering/scale.go/utiles/uint128" +) + +// Do not add, remove or change any of the field members. +type CallTransferAlowDeath struct { + Dest prim.MultiAddress + Value uint128.Uint128 +} + +func (this CallTransferAlowDeath) PalletIndex() uint8 { + return PalletIndex +} + +func (this CallTransferAlowDeath) PalletName() string { + return PalletName +} + +func (this CallTransferAlowDeath) CallIndex() uint8 { + return 0 +} + +func (this CallTransferAlowDeath) CallName() string { + return "transfer_allow_death" +} + +func (this *CallTransferAlowDeath) ToPayload() metadata.Payload { + var call = prim.Call{ + PalletIndex: this.PalletIndex(), + CallIndex: this.CallIndex(), + Fields: prim.AlreadyEncoded{Value: prim.Encoder.Encode(this)}, + } + + return metadata.NewPayload(call, this.PalletName(), this.CallName()) +} + +func (this *CallTransferAlowDeath) DecodeExtrinsic(tx *prim.DecodedExtrinsic) bool { + if this.PalletIndex() != tx.Call.PalletIndex { + return false + } + + if this.CallIndex() != tx.Call.CallIndex { + return false + } + + var bytes = tx.Call.Fields.ToBytes() + var decoder = prim.NewDecoder(bytes, 0) + decoder.Decode(this) + return true +} + +// Do not add, remove or change any of the field members. +type CallForceTransfer struct { + Source prim.MultiAddress + Dest prim.MultiAddress + Value uint128.Uint128 +} + +func (this CallForceTransfer) PalletIndex() uint8 { + return PalletIndex +} + +func (this CallForceTransfer) PalletName() string { + return PalletName +} + +func (this CallForceTransfer) CallIndex() uint8 { + return 2 +} + +func (this CallForceTransfer) CallName() string { + return "force_transfer" +} + +func (this *CallForceTransfer) ToPayload() metadata.Payload { + var call = prim.Call{ + PalletIndex: this.PalletIndex(), + CallIndex: this.CallIndex(), + Fields: prim.AlreadyEncoded{Value: prim.Encoder.Encode(this)}, + } + + return metadata.NewPayload(call, this.PalletName(), this.CallName()) +} + +func (this *CallForceTransfer) DecodeExtrinsic(tx *prim.DecodedExtrinsic) bool { + if this.PalletIndex() != tx.Call.PalletIndex { + return false + } + + if this.CallIndex() != tx.Call.CallIndex { + return false + } + + var decoder = prim.NewDecoder(tx.Call.Fields.ToBytes(), 0) + decoder.Decode(this) + return true +} + +// Do not add, remove or change any of the field members. +type CallTransferKeepAlive struct { + Dest prim.MultiAddress + Value uint128.Uint128 +} + +func (this CallTransferKeepAlive) PalletIndex() uint8 { + return PalletIndex +} + +func (this CallTransferKeepAlive) PalletName() string { + return PalletName +} + +func (this CallTransferKeepAlive) CallIndex() uint8 { + return 3 +} + +func (this CallTransferKeepAlive) CallName() string { + return "transfer_keep_alive" +} + +func (this *CallTransferKeepAlive) ToPayload() metadata.Payload { + var call = prim.Call{ + PalletIndex: this.PalletIndex(), + CallIndex: this.CallIndex(), + Fields: prim.AlreadyEncoded{Value: prim.Encoder.Encode(this)}, + } + + return metadata.NewPayload(call, this.PalletName(), this.CallName()) +} + +func (this *CallTransferKeepAlive) DecodeExtrinsic(tx *prim.DecodedExtrinsic) bool { + if this.PalletIndex() != tx.Call.PalletIndex { + return false + } + + if this.CallIndex() != tx.Call.CallIndex { + return false + } + + var decoder = prim.NewDecoder(tx.Call.Fields.ToBytes(), 0) + decoder.Decode(this) + return true +} + +// Do not add, remove or change any of the field members. +type CallTransferAll struct { + Dest prim.MultiAddress + KeepAlive bool +} + +func (this CallTransferAll) PalletIndex() uint8 { + return PalletIndex +} + +func (this CallTransferAll) PalletName() string { + return PalletName +} + +func (this CallTransferAll) CallIndex() uint8 { + return 4 +} + +func (this CallTransferAll) CallName() string { + return "transfer_all" +} + +func (this *CallTransferAll) ToPayload() metadata.Payload { + var call = prim.Call{ + PalletIndex: this.PalletIndex(), + CallIndex: this.CallIndex(), + Fields: prim.AlreadyEncoded{Value: prim.Encoder.Encode(this)}, + } + + return metadata.NewPayload(call, this.PalletName(), this.CallName()) +} + +func (this *CallTransferAll) DecodeExtrinsic(tx *prim.DecodedExtrinsic) bool { + if this.PalletIndex() != tx.Call.PalletIndex { + return false + } + + if this.CallIndex() != tx.Call.CallIndex { + return false + } + + var decoder = prim.NewDecoder(tx.Call.Fields.ToBytes(), 0) + decoder.Decode(this) + return true +} diff --git a/metadata/pallets/balances/events.go b/metadata/pallets/balances/events.go new file mode 100644 index 0000000..e2c3ab1 --- /dev/null +++ b/metadata/pallets/balances/events.go @@ -0,0 +1,49 @@ +package balances + +import ( + "go-sdk/metadata" +) + +// Do not add, remove or change any of the field members. +type EventDeposit struct { + Who metadata.AccountId + Amount metadata.Balance +} + +func (this EventDeposit) PalletIndex() uint8 { + return PalletIndex +} + +func (this EventDeposit) PalletName() string { + return PalletName +} + +func (this EventDeposit) EventIndex() uint8 { + return 7 +} + +func (this EventDeposit) EventName() string { + return "Deposit" +} + +// Do not add, remove or change any of the field members. +type EventWithdraw struct { + Who metadata.AccountId + Amount metadata.Balance +} + +func (this EventWithdraw) PalletIndex() uint8 { + return PalletIndex +} + +func (this EventWithdraw) PalletName() string { + return PalletName +} + +func (this EventWithdraw) EventIndex() uint8 { + return 8 +} + +func (this EventWithdraw) EventName() string { + return "Withdraw" +} diff --git a/metadata/pallets/balances/mod.go b/metadata/pallets/balances/mod.go new file mode 100644 index 0000000..baedb99 --- /dev/null +++ b/metadata/pallets/balances/mod.go @@ -0,0 +1,4 @@ +package balances + +const PalletIndex = 6 +const PalletName = "Balances" diff --git a/metadata/pallets/data_availability/calls.go b/metadata/pallets/data_availability/calls.go new file mode 100644 index 0000000..c0c5f4d --- /dev/null +++ b/metadata/pallets/data_availability/calls.go @@ -0,0 +1,96 @@ +package data_availability + +import ( + "go-sdk/metadata" + prim "go-sdk/primitives" +) + +// Do not add, remove or change any of the field members. +type CallCreateApplicationKey struct { + Key []uint8 +} + +func (this CallCreateApplicationKey) PalletIndex() uint8 { + return PalletIndex +} + +func (this CallCreateApplicationKey) PalletName() string { + return PalletName +} + +func (this CallCreateApplicationKey) CallIndex() uint8 { + return 0 +} + +func (this CallCreateApplicationKey) CallName() string { + return "create_application_key" +} + +func (this *CallCreateApplicationKey) ToPayload() metadata.Payload { + var call = prim.Call{ + PalletIndex: this.PalletIndex(), + CallIndex: this.CallIndex(), + Fields: prim.AlreadyEncoded{Value: prim.Encoder.Encode(this)}, + } + + return metadata.NewPayload(call, this.PalletName(), this.CallName()) +} + +func (this *CallCreateApplicationKey) DecodeExtrinsic(tx *prim.DecodedExtrinsic) bool { + if this.PalletIndex() != tx.Call.PalletIndex { + return false + } + + if this.CallIndex() != tx.Call.CallIndex { + return false + } + + var decoder = prim.NewDecoder(tx.Call.Fields.ToBytes(), 0) + decoder.Decode(this) + return true +} + +// Do not add, remove or change any of the field members. +type CallSubmitData struct { + Data []uint8 +} + +func (this CallSubmitData) PalletIndex() uint8 { + return PalletIndex +} + +func (this CallSubmitData) PalletName() string { + return PalletName +} + +func (this CallSubmitData) CallIndex() uint8 { + return 1 +} + +func (this CallSubmitData) CallName() string { + return "submit_data" +} + +func (this *CallSubmitData) ToPayload() metadata.Payload { + var call = prim.Call{ + PalletIndex: this.PalletIndex(), + CallIndex: this.CallIndex(), + Fields: prim.AlreadyEncoded{Value: prim.Encoder.Encode(this)}, + } + + return metadata.NewPayload(call, this.PalletName(), this.CallName()) +} + +func (this *CallSubmitData) DecodeExtrinsic(tx *prim.DecodedExtrinsic) bool { + if this.PalletIndex() != tx.Call.PalletIndex { + return false + } + + if this.CallIndex() != tx.Call.CallIndex { + return false + } + + var decoder = prim.NewDecoder(tx.Call.Fields.ToBytes(), 0) + decoder.Decode(this) + return true +} diff --git a/metadata/pallets/data_availability/events.go b/metadata/pallets/data_availability/events.go new file mode 100644 index 0000000..79954ef --- /dev/null +++ b/metadata/pallets/data_availability/events.go @@ -0,0 +1,51 @@ +package data_availability + +import ( + "go-sdk/metadata" + prim "go-sdk/primitives" +) + +// Do not add, remove or change any of the field members. +type EventApplicationKeyCreated struct { + Key []uint8 + Owner metadata.AccountId + Id uint32 +} + +func (this EventApplicationKeyCreated) PalletIndex() uint8 { + return PalletIndex +} + +func (this EventApplicationKeyCreated) PalletName() string { + return PalletName +} + +func (this EventApplicationKeyCreated) EventIndex() uint8 { + return 0 +} + +func (this EventApplicationKeyCreated) EventName() string { + return "ApplicationKeyCreated" +} + +// Do not add, remove or change any of the field members. +type EventDataSubmitted struct { + Who metadata.AccountId + DataHash prim.H256 +} + +func (this EventDataSubmitted) PalletIndex() uint8 { + return PalletIndex +} + +func (this EventDataSubmitted) PalletName() string { + return PalletName +} + +func (this EventDataSubmitted) EventIndex() uint8 { + return 1 +} + +func (this EventDataSubmitted) EventName() string { + return "DataSubmitted" +} diff --git a/metadata/pallets/data_availability/mod.go b/metadata/pallets/data_availability/mod.go new file mode 100644 index 0000000..c1fda60 --- /dev/null +++ b/metadata/pallets/data_availability/mod.go @@ -0,0 +1,4 @@ +package data_availability + +const PalletName = "DataAvailability" +const PalletIndex = 29 diff --git a/metadata/pallets/mod.go b/metadata/pallets/mod.go new file mode 100644 index 0000000..170d9fa --- /dev/null +++ b/metadata/pallets/mod.go @@ -0,0 +1 @@ +package pallets diff --git a/metadata/pallets/system/events.go b/metadata/pallets/system/events.go new file mode 100644 index 0000000..75d34e8 --- /dev/null +++ b/metadata/pallets/system/events.go @@ -0,0 +1,47 @@ +package system + +import ( + meta "go-sdk/metadata" +) + +// Do not add, remove or change any of the field members. +type EventExtrinsicSuccess struct { + DispatchInfo meta.DispatchInfo +} + +func (this EventExtrinsicSuccess) PalletIndex() uint8 { + return PalletIndex +} + +func (this EventExtrinsicSuccess) PalletName() string { + return PalletName +} + +func (this EventExtrinsicSuccess) EventIndex() uint8 { + return 0 +} + +func (this EventExtrinsicSuccess) EventName() string { + return "ExtrinsicSuccess" +} + +// Do not add, remove or change any of the field members. +type EventExtrinsicFailed struct { + DispatchInfo meta.DispatchInfo +} + +func (this EventExtrinsicFailed) PalletIndex() uint8 { + return PalletIndex +} + +func (this EventExtrinsicFailed) PalletName() string { + return PalletName +} + +func (this EventExtrinsicFailed) EventIndex() uint8 { + return 1 +} + +func (this EventExtrinsicFailed) EventName() string { + return "ExtrinsicFailed" +} diff --git a/metadata/pallets/system/mod.go b/metadata/pallets/system/mod.go new file mode 100644 index 0000000..dfedf66 --- /dev/null +++ b/metadata/pallets/system/mod.go @@ -0,0 +1,4 @@ +package system + +const PalletIndex = 0 +const PalletName = "System" diff --git a/metadata/pallets/transaction_payment/events.go b/metadata/pallets/transaction_payment/events.go new file mode 100644 index 0000000..7e8cf4e --- /dev/null +++ b/metadata/pallets/transaction_payment/events.go @@ -0,0 +1,30 @@ +package transaction_payment + +import ( + meta "go-sdk/metadata" + + "github.com/itering/scale.go/utiles/uint128" +) + +// Do not add, remove or change any of the field members. +type EventTransactionFeePaid struct { + Who meta.AccountId + ActualFee uint128.Uint128 + Tip uint128.Uint128 +} + +func (this EventTransactionFeePaid) PalletIndex() uint8 { + return PalletIndex +} + +func (this EventTransactionFeePaid) PalletName() string { + return PalletName +} + +func (this EventTransactionFeePaid) EventIndex() uint8 { + return 0 +} + +func (this EventTransactionFeePaid) EventName() string { + return "TransactionFeePaid" +} diff --git a/metadata/pallets/transaction_payment/mod.go b/metadata/pallets/transaction_payment/mod.go new file mode 100644 index 0000000..62a28a4 --- /dev/null +++ b/metadata/pallets/transaction_payment/mod.go @@ -0,0 +1,4 @@ +package transaction_payment + +const PalletName = "TransactionPayment" +const PalletIndex = 7 diff --git a/metadata/payload.go b/metadata/payload.go new file mode 100644 index 0000000..931b154 --- /dev/null +++ b/metadata/payload.go @@ -0,0 +1,27 @@ +package metadata + +import ( + "go-sdk/primitives" +) + +type Payload struct { + Call primitives.Call + palletName string + callName string +} + +func NewPayload(call primitives.Call, palletName string, callName string) Payload { + return Payload{ + Call: call, + palletName: palletName, + callName: callName, + } +} + +func (this *Payload) PalletName() string { + return this.palletName +} + +func (this *Payload) CallName() string { + return this.callName +} diff --git a/metadata/types.go b/metadata/types.go new file mode 100644 index 0000000..54d2f00 --- /dev/null +++ b/metadata/types.go @@ -0,0 +1,304 @@ +package metadata + +import ( + "github.com/vedhavyas/go-subkey/v2" + prim "go-sdk/primitives" + + "github.com/itering/scale.go/utiles/uint128" +) + +type Balance struct { + Value uint128.Uint128 +} + +func (this Balance) ToHuman() string { + var stringValue = this.Value.String() + + if len(stringValue) <= 18 { + var result = "0." + return result + removeTrailingZeros(stringValue) + " avail" + } + + var result = "" + for i := 0; i < len(stringValue); i++ { + result = string(stringValue[len(stringValue)-i-1]) + result + if i == 18 { + result = "." + result + } + } + + return removeTrailingZeros(result) + " avail" +} + +func removeTrailingZeros(s string) string { + for { + if len(s) == 0 { + break + } + if s[len(s)-1] != '0' { + break + } + s = s[:len(s)-1] + } + return s +} + +// Do not add, remove or change any of the field members. +type AccountId struct { + Value prim.H256 +} + +func (this AccountId) ToSS58() string { + return subkey.SS58Encode(this.Value.Value[:], 42) +} + +func (this AccountId) ToAddress() string { + return this.ToSS58() +} + +func (this AccountId) ToHuman() string { + return this.ToSS58() +} + +func NewAccountIdFromAddress(address string) (AccountId, error) { + var _, accountBytes, err = subkey.SS58Decode(address) + if err != nil { + return AccountId{}, err + } + var h256 = prim.NewH256FromByteSlice(accountBytes) + var res = AccountId{Value: h256} + return res, nil +} + +// Do not add, remove or change any of the field members. +type DispatchInfo struct { + Weight Weight + Class DispatchClass + PaysFee Pays + FeeModifier DispatchFeeModifier +} + +// Do not add, remove or change any of the field members. +type Weight struct { + RefTime uint64 + ProofSize uint64 +} + +// Do not add, remove or change any of the field members. +type DispatchClass struct { + VariantIndex uint8 +} + +func (this DispatchClass) ToString() string { + switch this.VariantIndex { + case 0: + return "Normal" + case 1: + return "Operational" + case 2: + return "Mandatory" + default: + panic("Unknown DispatchCall Variant Index") + } +} + +// Do not add, remove or change any of the field members. +type Pays struct { + VariantIndex uint8 +} + +func (this Pays) ToString() string { + switch this.VariantIndex { + case 0: + return "Yes" + case 1: + return "No" + default: + panic("Unknown Pays Variant Index") + } +} + +// Do not add, remove or change any of the field members. +type DispatchFeeModifier struct { + WeightMaximumFee prim.Option[uint128.Uint128] + WeightFeeDivider prim.Option[uint32] + WeightFeeMultiplier prim.Option[uint32] +} + +// Do not add, remove or change any of the field members. +type DispatchError struct { + VariantIndex uint8 + Module prim.Option[ModuleError] + Token prim.Option[TokenError] + Arithmetic prim.Option[ArithmeticError] + Transactional prim.Option[TransactionalError] +} + +func (this DispatchError) ToString() string { + switch this.VariantIndex { + case 0: + return "Other" + case 1: + return "CannotLookup" + case 2: + return "BadOrigin" + case 3: + return "Module" + case 4: + return "ConsumerRemaining" + case 5: + return "NoProviders" + case 6: + return "TooManyConsumers" + case 7: + return "Token" + case 8: + return "Arithmetic" + case 9: + return "Transactional" + case 10: + return "Exhausted" + case 11: + return "Corruption" + case 12: + return "Unavailable" + case 13: + return "RootNotAllowed" + default: + panic("Unknown DispatchError Variant Index") + } +} + +func (this DispatchError) EncodeTo(dest *string) { + prim.Encoder.EncodeTo(this.VariantIndex, dest) + + if this.Module.IsSome() { + prim.Encoder.EncodeTo(this.Module.Unwrap(), dest) + } + + if this.Token.IsSome() { + prim.Encoder.EncodeTo(this.Token.Unwrap(), dest) + } + + if this.Arithmetic.IsSome() { + prim.Encoder.EncodeTo(this.Arithmetic.Unwrap(), dest) + } + + if this.Transactional.IsSome() { + prim.Encoder.EncodeTo(this.Transactional.Unwrap(), dest) + } +} + +func (this *DispatchError) Decode(decoder *prim.Decoder) bool { + decoder.Decode(&this.VariantIndex) + + this.Module = prim.NewNone[ModuleError]() + this.Token = prim.NewNone[TokenError]() + this.Arithmetic = prim.NewNone[ArithmeticError]() + this.Transactional = prim.NewNone[TransactionalError]() + + switch this.VariantIndex { + case 0: + case 1: + case 2: + case 3: + var t ModuleError + decoder.Decode(&t) + this.Module.Set(t) + case 4: + case 5: + case 6: + case 7: + var t TokenError + decoder.Decode(&t) + this.Token.Set(t) + case 8: + var t ArithmeticError + decoder.Decode(&t) + this.Arithmetic.Set(t) + case 9: + var t TransactionalError + decoder.Decode(&t) + this.Transactional.Set(t) + case 10: + case 11: + case 12: + case 13: + default: + panic("Unknown DispatchError Variant Index while Decoding") + } + + return true +} + +// Do not add, remove or change any of the field members. +type ModuleError struct { + Index uint8 + Error [4]byte +} + +// Do not add, remove or change any of the field members. +type TokenError struct { + VariantIndex uint8 +} + +func (this TokenError) ToString() string { + switch this.VariantIndex { + case 0: + return "FundsUnavailable" + case 1: + return "OnlyProvider" + case 2: + return "BelowMinimum" + case 3: + return "CannotCreate" + case 4: + return "UnknownAsset" + case 5: + return "Frozen" + case 6: + return "Unsupported" + case 7: + return "CannotCreateHold" + case 8: + return "NotExpendable" + case 9: + return "Blocked" + default: + panic("Unknown TokenError Variant Index") + } +} + +// Do not add, remove or change any of the field members. +type ArithmeticError struct { + VariantIndex uint8 +} + +func (this ArithmeticError) ToString() string { + switch this.VariantIndex { + case 0: + return "Underflow" + case 1: + return "Overflow" + case 2: + return "DivisionByZero" + default: + panic("Unknown ArithmeticError Variant Index") + } +} + +// Do not add, remove or change any of the field members. +type TransactionalError struct { + VariantIndex uint8 +} + +func (this TransactionalError) ToString() string { + switch this.VariantIndex { + case 0: + return "LimitReached" + case 1: + return "NoLayer" + default: + panic("Unknown TransactionalError Variant Index") + } +} diff --git a/primitives/address.go b/primitives/address.go new file mode 100644 index 0000000..9da18f9 --- /dev/null +++ b/primitives/address.go @@ -0,0 +1,94 @@ +package primitives + +import ( + "errors" + "fmt" +) + +// Do not change the order of field members. +type MultiAddress struct { + Id Option[H256] + Index Option[uint32] + Raw Option[[]byte] + Address32 Option[[32]byte] + Address20 Option[[20]byte] +} + +func emptyMultiAddress() MultiAddress { + return MultiAddress{ + Id: NewNone[H256](), + Index: NewNone[uint32](), + Raw: NewNone[[]byte](), + Address32: NewNone[[32]byte](), + Address20: NewNone[[20]byte](), + } +} + +func NewMultiAddressId(value H256) MultiAddress { + address := emptyMultiAddress() + address.Id = NewSome(value) + return address +} + +func (this *MultiAddress) EncodeTo(dest *string) { + if this.Id.IsSome() { + Encoder.EncodeTo(uint8(0), dest) + Encoder.EncodeTo(this.Id.Unwrap(), dest) + } else if this.Index.IsSome() { + Encoder.EncodeTo(uint8(1), dest) + Encoder.EncodeTo(this.Index.Unwrap(), dest) + } else if this.Raw.IsSome() { + Encoder.EncodeTo(uint8(2), dest) + Encoder.EncodeTo(this.Raw.Unwrap(), dest) + } else if this.Address32.IsSome() { + Encoder.EncodeTo(uint8(3), dest) + Encoder.EncodeTo(this.Address32.Unwrap(), dest) + } else if this.Address20.IsSome() { + Encoder.EncodeTo(uint8(4), dest) + Encoder.EncodeTo(this.Address20.Unwrap(), dest) + } else { + panic("Something Went Wrong with MultiAddress EncodeTo") + } +} + +func (this *MultiAddress) Decode(decoder *Decoder) error { + result := emptyMultiAddress() + variantIndex := uint8(0) + decoder.Decode(&variantIndex) + if variantIndex == 0 { + value := H256{} + if err := decoder.Decode(&value); err != nil { + return err + } + result.Id = NewSome(value) + } else if variantIndex == 1 { + value := uint32(0) + if err := decoder.Decode(&value); err != nil { + return err + } + result.Index = NewSome(value) + } else if variantIndex == 2 { + value := []byte{} + if err := decoder.Decode(&value); err != nil { + return err + } + result.Raw = NewSome(value) + } else if variantIndex == 3 { + value := [32]byte{} + if err := decoder.Decode(&value); err != nil { + return err + } + result.Address32 = NewSome(value) + } else if variantIndex == 4 { + value := [20]byte{} + if err := decoder.Decode(&value); err != nil { + return err + } + result.Address20 = NewSome(value) + } else { + return errors.New(fmt.Sprintf(`MultiAddress Decode failure. Unknown Variant index: %v`, variantIndex)) + } + + *this = result + return nil +} diff --git a/primitives/already_encoded.go b/primitives/already_encoded.go new file mode 100644 index 0000000..871ea30 --- /dev/null +++ b/primitives/already_encoded.go @@ -0,0 +1,21 @@ +package primitives + +type AlreadyEncoded struct { + Value string +} + +func (this *AlreadyEncoded) EncodeTo(dest *string) { + *dest += this.Value +} + +func (this *AlreadyEncoded) ToHex() string { + return this.Value +} + +func (this *AlreadyEncoded) ToHexWith0x() string { + return "0x" + this.Value +} + +func (this *AlreadyEncoded) ToBytes() []byte { + return FromHex(this.Value) +} diff --git a/primitives/block.go b/primitives/block.go new file mode 100644 index 0000000..0569447 --- /dev/null +++ b/primitives/block.go @@ -0,0 +1,46 @@ +package primitives + +import "encoding/json" + +type Block struct { + Extrinsics []string + Header Header +} + +func NewBlock(rawJson string) Block { + var mappedData map[string]interface{} + if err := json.Unmarshal([]byte(rawJson), &mappedData); err != nil { + panic(err) + } + + if mappedData["block"] == nil { + panic("Block is missing block") + } + + mappedData2 := mappedData["block"].(map[string]interface{}) + if mappedData2["extrinsics"] == nil { + panic("Block is missing extrinsics") + } + + if mappedData2["header"] == nil { + panic("Block is missing header") + } + + headerJson, err2 := json.Marshal(mappedData2["header"]) + if err2 != nil { + panic(err2) + } + header := NewHeaderFromJson(string(headerJson)) + + extrinsicsRaw := mappedData2["extrinsics"].([]interface{}) + extrinsics := []string{} + + for i := 0; i < len(extrinsicsRaw); i++ { + extrinsics = append(extrinsics, extrinsicsRaw[i].(string)) + } + + return Block{ + Extrinsics: extrinsics, + Header: header, + } +} diff --git a/primitives/extrinsics_decoded.go b/primitives/extrinsics_decoded.go new file mode 100644 index 0000000..ac1ecbc --- /dev/null +++ b/primitives/extrinsics_decoded.go @@ -0,0 +1,81 @@ +package primitives + +import ( + "golang.org/x/crypto/blake2b" +) + +type DecodedExtrinsic struct { + Call Call + TxHash H256 + TxIndex uint32 + Signed Option[DecodedExtrinsicSigned] +} + +type DecodedExtrinsicSigned struct { + Address MultiAddress + Signature MultiSignature + Nonce uint32 + AppId uint32 +} + +func NewDecodedExtrinsic(extrinsic EncodedExtrinsic, txIndex uint32) (DecodedExtrinsic, error) { + decodedData := extrinsic.HexToBytes() + txHashArray := blake2b.Sum256(decodedData) + txHash := NewH256FromByteSlice(txHashArray[:]) + + totalLength := len(decodedData) + signedPart := NewNone[DecodedExtrinsicSigned]() + + // Reading Transaction Length + decoder := NewDecoder(decodedData, 0) + txLength := CompactU32{} + if err := decoder.Decode(&txLength); err != nil { + return DecodedExtrinsic{}, err + } + + if totalLength != int(txLength.Value)+decoder.Offset() { + panic("remainingLength is not equal to txLength + scaleDecoder.Data.Offset") + } + + // Checking if the message is signed + signed := uint8(0) + if err := decoder.Decode(&signed); err != nil { + return DecodedExtrinsic{}, err + } + // 132 is 0x84 + if signed == 132 { + multiAddress := MultiAddress{} + if err := decoder.Decode(&multiAddress); err != nil { + return DecodedExtrinsic{}, err + } + multiSignature := MultiSignature{} + if err := decoder.Decode(&multiSignature); err != nil { + return DecodedExtrinsic{}, err + } + extra := Extra{} + if err := decoder.Decode(&extra); err != nil { + return DecodedExtrinsic{}, err + } + + signedData := DecodedExtrinsicSigned{ + Address: multiAddress, + Signature: multiSignature, + Nonce: extra.Nonce, + AppId: extra.AppId, + } + + signedPart.Set(signedData) + } + + call := Call{} + if err := decoder.Decode(&call); err != nil { + return DecodedExtrinsic{}, err + } + + return DecodedExtrinsic{ + Call: call, + TxHash: txHash, + TxIndex: txIndex, + Signed: signedPart, + }, nil +} diff --git a/primitives/extrinsics_encoded.go b/primitives/extrinsics_encoded.go new file mode 100644 index 0000000..608965d --- /dev/null +++ b/primitives/extrinsics_encoded.go @@ -0,0 +1,67 @@ +package primitives + +import ( + SType "github.com/itering/scale.go/types" + "github.com/itering/scale.go/utiles" +) + +// Hex and Scale encoded extrinsic that stats with "0x" +type EncodedExtrinsic struct { + Value string +} + +func (this *EncodedExtrinsic) Encode() string { + return this.Value +} + +func (this *EncodedExtrinsic) ToHex() string { + return this.Value +} + +func (this *EncodedExtrinsic) ToHexWith0x() string { + return "0x" + this.ToHex() +} + +func (this *EncodedExtrinsic) HexToBytes() []byte { + return utiles.HexToBytes(this.Value) +} + +func (this *EncodedExtrinsic) Decode(txIndex uint32) (DecodedExtrinsic, error) { + return NewDecodedExtrinsic(*this, txIndex) +} + +func NewEncodedExtrinsic(payloadExtra *AlreadyEncoded, payloadCall *AlreadyEncoded, address MultiAddress, signature MultiSignature) EncodedExtrinsic { + encoded_inner := "" + + // "is signed" + transaction protocol version (4) + encoded_inner += "84" + + // Attach Address from Signer + address.EncodeTo(&encoded_inner) + + // Signature + signature.EncodeTo(&encoded_inner) + + // Payload + Call + payloadExtra.EncodeTo(&encoded_inner) + payloadCall.EncodeTo(&encoded_inner) + + innerLength := SType.Encode("Compact", len(encoded_inner)/2) + encoded := innerLength + encoded_inner + return EncodedExtrinsic{ + Value: encoded, + } +} + +func NewEncodedExtrinsicFromHex(hexString string) EncodedExtrinsic { + if len(hexString) < 2 { + panic("Not Possible") + } + if hexString[0] == '0' && hexString[1] == 'x' { + hexString = hexString[2:] + } + + return EncodedExtrinsic{ + Value: hexString, + } +} diff --git a/primitives/extrinsics_payload.go b/primitives/extrinsics_payload.go new file mode 100644 index 0000000..e33f346 --- /dev/null +++ b/primitives/extrinsics_payload.go @@ -0,0 +1,160 @@ +package primitives + +import ( + "math" + "math/bits" + + "github.com/itering/scale.go/utiles" + "github.com/itering/scale.go/utiles/uint128" + "github.com/vedhavyas/go-subkey/v2" + "golang.org/x/crypto/blake2b" +) + +// Do not change the order of field members. +type Additional struct { + SpecVersion uint32 + TxVersion uint32 + GenesisHash H256 + ForkHash H256 +} + +// Do not change the order of field members. +type Call struct { + PalletIndex uint8 + CallIndex uint8 + Fields AlreadyEncoded +} + +func NewCall(palletIndex uint8, callIndex uint8, fields AlreadyEncoded) Call { + return Call{ + PalletIndex: palletIndex, + CallIndex: callIndex, + Fields: fields, + } +} + +func (this *Call) Decode(decoder *Decoder) error { + // Call Index + if err := decoder.Decode(&this.PalletIndex); err != nil { + return err + } + if err := decoder.Decode(&this.CallIndex); err != nil { + return err + } + + // Call Data + dataBytes := decoder.NextBytes(decoder.RemainingLength()) + this.Fields = AlreadyEncoded{Value: ToHex(dataBytes)} + return nil +} + +// Do not change the order of field members. +type Era struct { + period uint64 + phase uint64 +} + +func (this *Era) EncodeTo(dest *string) { + quantizeFactor := math.Max(float64(this.period>>12), 1) + trailingZeros := bits.TrailingZeros16(uint16(this.period)) + encoded := uint16(float64(this.phase)/quantizeFactor)<<4 | uint16(math.Min(15, math.Max(1, float64(trailingZeros-1)))) + + first := byte(encoded & 0xff) + second := byte(encoded >> 8) + + Encoder.EncodeTo(uint8(first), dest) + Encoder.EncodeTo(uint8(second), dest) +} + +func (this *Era) Decode(decoder *Decoder) error { + isImmortal := uint8(0) + if err := decoder.Decode(&isImmortal); err != nil { + return err + } + + if isImmortal == 0 { + return nil + } + + first := isImmortal + second := uint8(0) + if err := decoder.Decode(&second); err != nil { + return err + } + + encoded := uint16(first) | (uint16(second) << 8) + + trailingZeros := uint16(encoded&0xF) + 1 // Lower 4 bits + 1 + quantizedPhase := encoded >> 4 // Upper 12 bits + + quantizeFactor := math.Max(float64(this.period>>12), 1) + this.phase = uint64(float64(quantizedPhase) * quantizeFactor) + this.period = uint64(uint16(1 << trailingZeros)) + + return nil +} + +// Mortal describes a mortal era based on a period of validity and a block number on which it should start +func NewEra(period uint64, blockNumber uint64) Era { + calPeriod := uint64(math.Pow(2, math.Ceil(math.Log2(float64(period))))) + if calPeriod < 4 { + calPeriod = 4 + } + if calPeriod > (1 << 16) { + calPeriod = 1 << 16 + } + + phase := blockNumber % calPeriod + quantize_factor := math.Max(float64(calPeriod>>12), 1) + quantized_phase := float64(phase) / quantize_factor * quantize_factor + + return Era{ + period: calPeriod, + phase: uint64(quantized_phase), + } +} + +// Do not change the order of field members. +type Extra struct { + Era Era + Nonce uint32 `scale:"compact"` + Tip uint128.Uint128 `scale:"compact"` + AppId uint32 `scale:"compact"` +} + +type UnsignedPayload struct { + Call Call + Extra Extra + Additional Additional +} + +func (this UnsignedPayload) Encode() UnsignedEncodedPayload { + return UnsignedEncodedPayload{ + Call: AlreadyEncoded{Value: Encoder.Encode(this.Call)}, + Extra: AlreadyEncoded{Value: Encoder.Encode(this.Extra)}, + Additional: AlreadyEncoded{Value: Encoder.Encode(this.Additional)}, + } +} + +type UnsignedEncodedPayload struct { + Call AlreadyEncoded + Extra AlreadyEncoded + Additional AlreadyEncoded +} + +func (this *UnsignedEncodedPayload) Sign(signer subkey.KeyPair) ([]byte, error) { + data := "" + Encoder.EncodeTo(this.Call, &data) + Encoder.EncodeTo(this.Extra, &data) + Encoder.EncodeTo(this.Additional, &data) + + decodedData := utiles.HexToBytes(data) + + if len(decodedData) > 256 { + blakeSum := blake2b.Sum256(decodedData) + return signer.Sign([]byte(blakeSum[:])) + } else { + return signer.Sign(decodedData) + } + +} diff --git a/primitives/extrinsics_payload_test.go b/primitives/extrinsics_payload_test.go new file mode 100644 index 0000000..d7ed664 --- /dev/null +++ b/primitives/extrinsics_payload_test.go @@ -0,0 +1,40 @@ +package primitives + +import ( + "reflect" + "testing" + + "github.com/itering/scale.go/utiles/uint128" +) + +func TestEraDecode(t *testing.T) { + var expected = NewEra(5, 20) + var encode = Encoder.Encode(expected) + var input = FromHex(encode) + var decoder = NewDecoder(input, 0) + + var actual = Era{} + decoder.Decode(&actual) + if !reflect.DeepEqual(actual, expected) { + t.Fatalf(`Decoder Era Failure. Input %v, Output %v, Expected Output %v`, input, actual, expected) + } +} + +func TestExtraDecode(t *testing.T) { + var era = NewEra(5, 20) + var expected = Extra{ + Era: era, + Nonce: 5, + Tip: uint128.From64(uint64(123)), + AppId: 3, + } + var encode = Encoder.Encode(expected) + var input = FromHex(encode) + var decoder = NewDecoder(input, 0) + + var actual = Extra{} + decoder.Decode(&actual) + if !reflect.DeepEqual(actual, expected) { + t.Fatalf(`Decoder Extra Failure. Input %v, Output %v, Expected Output %v`, input, actual, expected) + } +} diff --git a/primitives/extrinsics_sign.go b/primitives/extrinsics_sign.go new file mode 100644 index 0000000..66500fa --- /dev/null +++ b/primitives/extrinsics_sign.go @@ -0,0 +1,27 @@ +package primitives + +import ( + "github.com/vedhavyas/go-subkey/v2" +) + +func CreateSigned(call Call, extra Extra, additional Additional, kp subkey.KeyPair) EncodedExtrinsic { + unsignedPayload := UnsignedPayload{ + Call: call, + Extra: extra, + Additional: additional, + } + unsignedEncodedPayload := unsignedPayload.Encode() + + rawSignature, err := unsignedEncodedPayload.Sign(kp) + if err != nil { + panic(err) + } + + accountId := NewH256FromByteSlice(kp.AccountID()) + signature := NewH512FromByteSlice(rawSignature) + multiAddress := NewMultiAddressId(accountId) + multiSignature := NewMultiSignatureSr(signature) + encodedTransaction := NewEncodedExtrinsic(&unsignedEncodedPayload.Extra, &unsignedEncodedPayload.Call, multiAddress, multiSignature) + return encodedTransaction + +} diff --git a/primitives/hash_h256.go b/primitives/hash_h256.go new file mode 100644 index 0000000..49e3827 --- /dev/null +++ b/primitives/hash_h256.go @@ -0,0 +1,38 @@ +package primitives + +import ( + SUtiles "github.com/itering/scale.go/utiles" +) + +type H256 struct { + Value [32]byte +} + +func (this H256) ToHex() string { + return SUtiles.BytesToHex(this.Value[:]) +} + +func (this H256) ToHexWith0x() string { + return "0x" + this.ToHex() +} + +func (this H256) ToRpcParam() string { + return "\"" + this.ToHexWith0x() + "\"" +} + +func NewH256FromHexString(hexString string) H256 { + value := SUtiles.HexToBytes(hexString) + if len(value) != 32 { + panic("Uppps it's not 32") + } + + return H256{Value: [32]byte(value)} +} + +func NewH256FromByteSlice(array []byte) H256 { + if len(array) != 32 { + panic("Byte Slice for H256 needs to be 32 elements long.") + } + + return H256{Value: [32]byte(array)} +} diff --git a/primitives/hash_h512.go b/primitives/hash_h512.go new file mode 100644 index 0000000..e9973c9 --- /dev/null +++ b/primitives/hash_h512.go @@ -0,0 +1,38 @@ +package primitives + +import ( + SUtiles "github.com/itering/scale.go/utiles" +) + +type H512 struct { + Value [64]byte +} + +func (this *H512) ToHex() string { + return SUtiles.BytesToHex(this.Value[:]) +} + +func (this *H512) ToHexWith0x() string { + return "0x" + this.ToHex() +} + +func (this *H512) ToRpcParam() string { + return "\"" + this.ToHexWith0x() + "\"" +} + +func NewH512FromHexString(hexString string) H512 { + value := SUtiles.HexToBytes(hexString) + if len(value) != 64 { + panic("Uppps it's not 64") + } + + return H512{Value: [64]byte(value)} +} + +func NewH512FromByteSlice(array []byte) H512 { + if len(array) != 64 { + panic("Byte Slice for H512 needs to be 64 elements long.") + } + + return H512{Value: [64]byte(array)} +} diff --git a/primitives/hash_h520.go b/primitives/hash_h520.go new file mode 100644 index 0000000..b2352ad --- /dev/null +++ b/primitives/hash_h520.go @@ -0,0 +1,38 @@ +package primitives + +import ( + SUtiles "github.com/itering/scale.go/utiles" +) + +type H520 struct { + Value [65]byte +} + +func (this *H520) ToHex() string { + return SUtiles.BytesToHex(this.Value[:]) +} + +func (this *H520) ToHexWith0x() string { + return "0x" + this.ToHex() +} + +func (this *H520) ToRpcParam() string { + return "\"" + this.ToHexWith0x() + "\"" +} + +func NewH520FromHexString(hexString string) H520 { + value := SUtiles.HexToBytes(hexString) + if len(value) != 65 { + panic("Uppps it's not 65") + } + + return H520{Value: [65]byte(value)} +} + +func NewH520FromByteSlice(array []byte) H520 { + if len(array) != 65 { + panic("Byte Slice for H520 needs to be 65 elements long.") + } + + return H520{Value: [65]byte(array)} +} diff --git a/primitives/header.go b/primitives/header.go new file mode 100644 index 0000000..d76f664 --- /dev/null +++ b/primitives/header.go @@ -0,0 +1,52 @@ +package primitives + +import ( + "encoding/json" + "strconv" +) + +type Header struct { + // Missing + // digest + // extension + ExtrinsicsRoot H256 + Number uint32 + ParentHash H256 + StateRoot H256 +} + +func NewHeaderFromJson(rawJson string) Header { + var mappedData map[string]interface{} + if err := json.Unmarshal([]byte(rawJson), &mappedData); err != nil { + panic(err) + } + + if mappedData["extrinsicsRoot"] == nil { + panic("Header is missing extrinsicsRoot") + } + if mappedData["number"] == nil { + panic("Header is missing number") + } + if mappedData["parentHash"] == nil { + panic("Header is missing parentHash") + } + if mappedData["stateRoot"] == nil { + panic("Header is missing stateRoot") + } + + // + extrinsicsRoot := NewH256FromHexString(mappedData["extrinsicsRoot"].(string)) + parentHash := NewH256FromHexString(mappedData["parentHash"].(string)) + stateRoot := NewH256FromHexString(mappedData["stateRoot"].(string)) + number, err := strconv.ParseUint(mappedData["number"].(string)[2:], 16, 32) + if err != nil { + panic(err) + } + + return Header{ + ExtrinsicsRoot: extrinsicsRoot, + Number: uint32(number), + ParentHash: parentHash, + StateRoot: stateRoot, + } +} diff --git a/primitives/runtime_version.go b/primitives/runtime_version.go new file mode 100644 index 0000000..334f3ad --- /dev/null +++ b/primitives/runtime_version.go @@ -0,0 +1,64 @@ +package primitives + +import ( + "encoding/json" +) + +type RuntimeVersion struct { + // Missing + // apis + SpecVersion uint32 + TxVersion uint32 + ImplVersion uint32 + AuthoringVersion uint32 + StateVersion uint32 + SpecName string + ImplName string +} + +func NewRuntimeVersionFromJson(rawJson string) RuntimeVersion { + var mappedData map[string]interface{} + if err := json.Unmarshal([]byte(rawJson), &mappedData); err != nil { + panic(err) + } + + if mappedData["specVersion"] == nil { + panic("Header is missing specVersion") + } + if mappedData["transactionVersion"] == nil { + panic("Header is missing transactionVersion") + } + if mappedData["implVersion"] == nil { + panic("Header is missing implVersion") + } + if mappedData["authoringVersion"] == nil { + panic("Header is missing authoringVersion") + } + if mappedData["stateVersion"] == nil { + panic("Header is missing stateVersion") + } + if mappedData["specName"] == nil { + panic("Header is missing specName") + } + if mappedData["implName"] == nil { + panic("Header is missing implName") + } + + specVersion := uint32(mappedData["specVersion"].(float64)) + txVersion := uint32(mappedData["transactionVersion"].(float64)) + implVersion := uint32(mappedData["implVersion"].(float64)) + authoringVersion := uint32(mappedData["authoringVersion"].(float64)) + stateVersion := uint32(mappedData["stateVersion"].(float64)) + specName := mappedData["specName"].(string) + implName := mappedData["implName"].(string) + + return RuntimeVersion{ + SpecVersion: specVersion, + TxVersion: txVersion, + ImplVersion: implVersion, + AuthoringVersion: authoringVersion, + StateVersion: stateVersion, + SpecName: specName, + ImplName: implName, + } +} diff --git a/primitives/scale_decoder.go b/primitives/scale_decoder.go new file mode 100644 index 0000000..9e6a23a --- /dev/null +++ b/primitives/scale_decoder.go @@ -0,0 +1,328 @@ +package primitives + +import ( + "errors" + "fmt" + "math/big" + "reflect" + + SType "github.com/itering/scale.go/types" + "github.com/itering/scale.go/types/scaleBytes" + "github.com/itering/scale.go/utiles/uint128" + "github.com/shopspring/decimal" +) + +type Decoder struct { + ScaleBytes scaleBytes.ScaleBytes +} + +// Fixed arrays +func (this *Decoder) array(value reflect.Value) error { + elemType := value.Type().Elem() + arrayType := reflect.ArrayOf(value.Len(), elemType) + arrayPointer := reflect.New(arrayType) + newArray := arrayPointer.Elem() + + for i := 0; i < int(value.Len()); i++ { + elem := reflect.New(elemType).Elem() + + if err := this.Decode(elem.Addr().Interface()); err != nil { + return err + } + + newArray.Index(i).Set(elem) + } + + value.Set(newArray) + return nil +} + +// Dynamic arrays +func (this *Decoder) slice(value reflect.Value) error { + len := CompactU32{} + if err := this.Decode(&len); err != nil { + return err + } + + elemType := value.Type().Elem() + newSlice := reflect.MakeSlice(value.Type(), int(len.Value), int(len.Value)) + + for i := 0; i < int(len.Value); i++ { + elem := reflect.New(elemType).Elem() + if err := this.Decode(elem.Addr().Interface()); err != nil { + return err + } + + newSlice.Index(i).Set(elem) + } + + value.Set(newSlice) + return nil +} + +func (this *Decoder) callMethod(value reflect.Value) error { + methodName := "Decode" + method := value.MethodByName(methodName) + + args := []reflect.Value{reflect.ValueOf(this)} + results := method.Call(args) + + if len(results) == 0 { + return errors.New(`Decoder failed. Method Decode was called but the result of the call has no return values`) + } + + res := results[0].Interface() + if res == nil { + return nil + } + + return res.(error) +} + +func (this *Decoder) structureFields(value reflect.Value) error { + valueType := value.Type() + + for i := 0; i < valueType.NumField(); i++ { + field := valueType.Field(i) + if !field.IsExported() { + return errors.New(fmt.Sprintf(`Decoder failed. Struct field is not exported. Field Name: %v`, field.Name)) + } + + scaleTag := field.Tag.Get("scale") + if scaleTag == "ignore" { + continue + } + + isCompact := scaleTag == "compact" + fieldValue := value.Field(i) + if err := this.decodeInner(fieldValue.Addr(), isCompact); err != nil { + return err + } + } + + return nil +} + +func (this *Decoder) primitives(value reflect.Value, isCompact bool) (error, bool) { + kind := value.Kind().String() + name := value.Type().Name() + + if !isCompact { + if kind == "bool" { + if !this.HasAtLeastRemainingBytes(1) { + return errors.New(`Decoder failed. Out of Bytes`), true + } + + decoder := SType.Bool{} + decoder.Init(this.ScaleBytes, nil) + decoder.Process() + this.ScaleBytes.Offset = decoder.Data.Offset + + res := decoder.Value.(bool) + value.Set(reflect.ValueOf(res)) + return nil, true + } + if kind == "uint8" { + if !this.HasAtLeastRemainingBytes(1) { + return errors.New(`Decoder failed. Out of Bytes`), true + } + + decoder := SType.U8{} + decoder.Init(this.ScaleBytes, nil) + decoder.Process() + + this.ScaleBytes.Offset = decoder.Data.Offset + + res := uint8(decoder.Value.(int)) + value.Set(reflect.ValueOf(res)) + return nil, true + } + if kind == "uint16" { + if !this.HasAtLeastRemainingBytes(2) { + return errors.New(`Decoder failed. Out of Bytes`), true + } + + decoder := SType.U16{} + decoder.Init(this.ScaleBytes, nil) + decoder.Process() + + this.ScaleBytes.Offset = decoder.Data.Offset + + res := decoder.Value.(uint16) + value.Set(reflect.ValueOf(res)) + return nil, true + } + if kind == "uint32" { + if !this.HasAtLeastRemainingBytes(3) { + return errors.New(`Decoder failed. Out of Bytes`), true + } + + decoder := SType.U32{} + decoder.Init(this.ScaleBytes, nil) + decoder.Process() + + this.ScaleBytes.Offset = decoder.Data.Offset + + res := decoder.Value.(uint32) + value.Set(reflect.ValueOf(res)) + return nil, true + } + if kind == "uint64" { + if !this.HasAtLeastRemainingBytes(4) { + return errors.New(`Decoder failed. Out of Bytes`), true + } + + decoder := SType.U64{} + decoder.Init(this.ScaleBytes, nil) + decoder.Process() + + this.ScaleBytes.Offset = decoder.Data.Offset + + res := decoder.Value.(uint64) + value.Set(reflect.ValueOf(res)) + return nil, true + } + if kind == "string" { + decoder := SType.String{} + decoder.Init(this.ScaleBytes, nil) + decoder.Process() + + this.ScaleBytes.Offset = decoder.Data.Offset + + res := decoder.Value.(string) + value.Set(reflect.ValueOf(res)) + return nil, true + } + if name == "Uint128" { + if !this.HasAtLeastRemainingBytes(8) { + return errors.New(`Decoder failed. Out of Bytes`), true + } + + decoder := SType.U128{} + decoder.Init(this.ScaleBytes, nil) + decoder.Process() + + this.ScaleBytes.Offset = decoder.Data.Offset + + valueDecoded, _ := new(big.Int).SetString(decoder.Value.(string), 10) + res := uint128.FromBig(valueDecoded) + + value.Set(reflect.ValueOf(res)) + return nil, true + } + } else { + if kind == "uint32" { + decoder := SType.CompactU32{} + decoder.Init(this.ScaleBytes, nil) + decoder.Process() + + this.ScaleBytes.Offset = decoder.Data.Offset + res := uint32(decoder.Value.(int)) + value.Set(reflect.ValueOf(res)) + return nil, true + + } + if kind == "uint64" { + decoder := SType.Compact{} + options := SType.ScaleDecoderOption{} + options.SubType = "u64" + decoder.Init(this.ScaleBytes, &options) + decoder.Process() + + this.ScaleBytes.Offset = decoder.Data.Offset + res := decoder.Value.(uint64) + value.Set(reflect.ValueOf(res)) + return nil, true + } + + if name == "Uint128" { + decoder := SType.Compact{} + options := SType.ScaleDecoderOption{} + options.SubType = "u128" + decoder.Init(this.ScaleBytes, &options) + decoder.Process() + + this.ScaleBytes.Offset = decoder.Data.Offset + + valueBytes := decoder.Value.(decimal.Decimal) + valueDecoded, _ := new(big.Int).SetString(valueBytes.String(), 10) + + res := uint128.FromBig(valueDecoded) + value.Set(reflect.ValueOf(res)) + return nil, true + } + } + + return nil, false +} + +func (this *Decoder) Decode(value interface{}) error { + valueOf := reflect.ValueOf(value) + return this.decodeInner(valueOf, false) +} + +func (this *Decoder) decodeInner(value reflect.Value, isCompact bool) error { + if value.Kind() != reflect.Ptr { + return errors.New("Decoder failed. The passed value is not of pointer type") + } + + if !value.Elem().CanSet() { + return errors.New("Decoder failed. The passed value cannot be changed. CanSet is set to false") + } + + if this.hasCallMethod(value) { + return this.callMethod(value) + } + + pointee := value.Elem() + if res, ok := this.primitives(pointee, isCompact); ok { + return res + } + + switch pointee.Kind() { + case reflect.Slice: + return this.slice(pointee) + case reflect.Array: + return this.array(pointee) + case reflect.Struct: + return this.structureFields(pointee) + default: + elemKind := pointee.Kind() + elemName := pointee.Type().Name() + return errors.New(fmt.Sprintf(`Decoder failed. Unknown Value. Name: %v Type: %v`, elemName, elemKind)) + } +} + +func (this *Decoder) hasCallMethod(value reflect.Value) bool { + methodName := "Decode" + method := value.MethodByName(methodName) + + return method.IsValid() +} + +func NewDecoder(data []byte, offset int) Decoder { + return Decoder{ + ScaleBytes: scaleBytes.ScaleBytes{Data: data, Offset: offset}, + } +} + +func (this *Decoder) Offset() int { + return this.ScaleBytes.Offset +} + +func (this *Decoder) RemainingLength() int { + return this.ScaleBytes.GetRemainingLength() +} + +func (this *Decoder) HasAtLeastRemainingBytes(atLeast int) bool { + return this.ScaleBytes.GetRemainingLength() >= atLeast +} + +func (this *Decoder) NextBytes(length int) []byte { + return this.ScaleBytes.GetNextBytes(length) +} + +// This is just a different name for GetNextBytes +func (this *Decoder) StaticArray(byteCount int) []byte { + return this.ScaleBytes.GetNextBytes(byteCount) +} diff --git a/primitives/scale_decoder_test.go b/primitives/scale_decoder_test.go new file mode 100644 index 0000000..4f16dac --- /dev/null +++ b/primitives/scale_decoder_test.go @@ -0,0 +1,312 @@ +package primitives + +import ( + "math/big" + "reflect" + "testing" + + "github.com/itering/scale.go/utiles/uint128" +) + +func TestDecoderBool(t *testing.T) { + var testParameters = map[string]bool{} + // Min + testParameters["0x00"] = false + // Max + testParameters["0x01"] = true + + for key, expected := range testParameters { + var decoder = NewDecoder(FromHex(key), 0) + var actual = false + decoder.Decode(&actual) + if actual != expected { + t.Fatalf(`Decoder Bool Failure. Input %v, Output %v, Expected Output %v`, key, actual, expected) + } + } +} + +func TestDecoderUint8(t *testing.T) { + var testParameters = map[string]uint8{} + // Min + testParameters["0x00"] = 0 + // Min + 1 + testParameters["0x01"] = 1 + // Mid + testParameters["0x80"] = 128 + // Max - 1 + testParameters["0xfe"] = 254 + // Max + testParameters["0xff"] = 255 + + for key, expected := range testParameters { + var decoder = NewDecoder(FromHex(key), 0) + var actual = uint8(0) + decoder.Decode(&actual) + if actual != expected { + t.Fatalf(`Decoder Uint8 Failure. Input %v, Output %v, Expected Output %v`, key, actual, expected) + } + } +} + +func TestDecoderUint16(t *testing.T) { + var testParameters = map[string]uint16{} + // Min + testParameters["0x0000"] = 0 + // Min + 1 + testParameters["0x0100"] = 1 + // Mid + testParameters["0x0080"] = 32768 + // Max - 1 + testParameters["0xfeff"] = 65534 + // Max + testParameters["0xffff"] = 65535 + + for key, expected := range testParameters { + var decoder = NewDecoder(FromHex(key), 0) + var actual = uint16(0) + decoder.Decode(&actual) + if actual != expected { + t.Fatalf(`Decoder Uint16 Failure. Input %v, Output %v, Expected Output %v`, key, actual, expected) + } + } +} + +func TestDecoderUint32(t *testing.T) { + var testParameters = map[string]uint32{} + // Min + testParameters["0x00000000"] = 0 + // Min + 1 + testParameters["0x01000000"] = 1 + // Mid + testParameters["0x00000080"] = 2147483648 + // Max - 1 + testParameters["0xfeffffff"] = 4294967294 + // Max + testParameters["0xffffffff"] = 4294967295 + + for key, expected := range testParameters { + var decoder = NewDecoder(FromHex(key), 0) + var actual = uint32(0) + decoder.Decode(&actual) + if actual != expected { + t.Fatalf(`Decoder Uint32 Failure. Input %v, Output %v, Expected Output %v`, key, actual, expected) + } + } +} + +func TestDecoderUint64(t *testing.T) { + var testParameters = map[string]uint64{} + // Min + testParameters["0x0000000000000000"] = 0 + // Min + 1 + testParameters["0x0100000000000000"] = 1 + // Mid + testParameters["0xffffffffffffff7f"] = 9223372036854775807 + // Max - 1 + testParameters["0xfeffffffffffffff"] = 18446744073709551614 + // Max + testParameters["0xffffffffffffffff"] = 18446744073709551615 + + for key, expected := range testParameters { + var decoder = NewDecoder(FromHex(key), 0) + var actual = uint64(0) + decoder.Decode(&actual) + if actual != expected { + t.Fatalf(`Decoder Uint64 Failure. Input %v, Output %v, Expected Output %v`, key, actual, expected) + } + } +} + +func TestDecoderUint128(t *testing.T) { + var testParameters = map[string]uint128.Uint128{} + // Min + var res0, _ = new(big.Int).SetString("0", 10) + testParameters["0x00000000000000000000000000000000"] = uint128.FromBig(res0) + // Min + 1 + var res1, _ = new(big.Int).SetString("1", 10) + testParameters["0x01000000000000000000000000000000"] = uint128.FromBig(res1) + var res2, _ = new(big.Int).SetString("9223372036854775807", 10) + testParameters["0xffffffffffffff7f0000000000000000"] = uint128.FromBig(res2) + var res7, _ = new(big.Int).SetString("18446744073709551615", 10) + testParameters["0xffffffffffffffff0000000000000000"] = uint128.FromBig(res7) + var res8, _ = new(big.Int).SetString("18446744073709551616", 10) + testParameters["0x00000000000000000100000000000000"] = uint128.FromBig(res8) + + for key, expected := range testParameters { + var decoder = NewDecoder(FromHex(key), 0) + var actual = uint128.Uint128{} + decoder.Decode(&actual) + if actual != expected { + t.Fatalf(`Decoder Uint128 Failure. Input %v, Output %v, Expected Output %v`, key, actual, expected) + } + } +} + +func TestDecoderCompactU32(t *testing.T) { + var testParameters = map[string]uint32{} + // Min + testParameters["0x00"] = 0 + // Min + 1 + testParameters["0x04"] = 1 + // Mid + testParameters["0x0300000080"] = 2147483648 + // Max - 1 + testParameters["0x03feffffff"] = 4294967294 + // Max + testParameters["0x03ffffffff"] = 4294967295 + + for key, expected := range testParameters { + var decoder = NewDecoder(FromHex(key), 0) + var actual = CompactU32{} + decoder.Decode(&actual) + if actual.Value != expected { + t.Fatalf(`Decoder Compact Uint32 Failure. Input %v, Output %v, Expected Output %v`, key, actual, expected) + } + } +} + +func TestDecoderCompactU64(t *testing.T) { + var testParameters = map[string]uint64{} + // Min + testParameters["0x00"] = 0 + // Min + 1 + testParameters["0x04"] = 1 + // Mid + testParameters["0x13ffffffffffffff7f"] = 9223372036854775807 + // Max - 1 + testParameters["0x13feffffffffffffff"] = 18446744073709551614 + // Max + testParameters["0x13ffffffffffffffff"] = 18446744073709551615 + + for key, expected := range testParameters { + var decoder = NewDecoder(FromHex(key), 0) + var actual = CompactU64{} + decoder.Decode(&actual) + if actual.Value != expected { + t.Fatalf(`Decoder Compact Uint64 Failure. Input %v, Output %v, Expected Output %v`, key, actual, expected) + } + } +} + +func TestDecoderCompactUint128(t *testing.T) { + var testParameters = map[string]uint128.Uint128{} + // Min + var res0, _ = new(big.Int).SetString("0", 10) + testParameters["0x00"] = uint128.FromBig(res0) + // Min + 1 + var res1, _ = new(big.Int).SetString("1", 10) + testParameters["0x04"] = uint128.FromBig(res1) + var res2, _ = new(big.Int).SetString("9223372036854775807", 10) + testParameters["0x13ffffffffffffff7f"] = uint128.FromBig(res2) + var res7, _ = new(big.Int).SetString("18446744073709551615", 10) + testParameters["0x13ffffffffffffffff"] = uint128.FromBig(res7) + var res8, _ = new(big.Int).SetString("18446744073709551616", 10) + testParameters["0x17000000000000000001"] = uint128.FromBig(res8) + + for key, expected := range testParameters { + var decoder = NewDecoder(FromHex(key), 0) + var actual = CompactU128{} + decoder.Decode(&actual) + if actual.Value != expected { + t.Fatalf(`Decoder Compact Uint128 Failure. Input %v, Output %v, Expected Output %v`, key, actual, expected) + } + } +} + +func TestDecoderArray(t *testing.T) { + // Primitives + { + var expected = [5]byte{0, 1, 2, 3, 4} + var input = "0x0001020304" + var actual = [5]byte{} + var decoder = NewDecoder(FromHex(input), 0) + decoder.Decode(&actual) + if !reflect.DeepEqual(actual, expected) { + t.Fatalf(`Decoder Array Failure. Input %v, Output %v, Expected Output %v`, input, actual, expected) + } + } + + // Structures + { + var input = "0x000102030414000102030480000000000000003c000102030414000102030480000000000000003c" + var el = DummyStruct{ + Array: [5]byte{0, 1, 2, 3, 4}, + Slice: []byte{0, 1, 2, 3, 4}, + Primitive: 128, + Compact: 15, + } + var el2 = el + var expected = [2]DummyStruct{el, el2} + var actual = [2]DummyStruct{} + var decoder = NewDecoder(FromHex(input), 0) + decoder.Decode(&actual) + if !reflect.DeepEqual(actual, expected) { + t.Fatalf(`Decoder Array Failure. Input %v, Output %v, Expected Output %v`, input, actual, expected) + } + } +} + +func TestDecoderSlice(t *testing.T) { + // Primitives + { + var input = "0x140001020304" + var expected = []byte{0, 1, 2, 3, 4} + var actual = []byte{} + var decoder = NewDecoder(FromHex(input), 0) + decoder.Decode(&actual) + if !reflect.DeepEqual(actual, expected) { + t.Fatalf(`Decoder Slice Failure. Input %v, Output %v, Expected Output %v`, input, actual, expected) + } + } + + // Structures + { + var input = "0x08000102030414000102030480000000000000003c000102030414000102030480000000000000003c" + var el = DummyStruct{ + Array: [5]byte{0, 1, 2, 3, 4}, + Slice: []byte{0, 1, 2, 3, 4}, + Primitive: 128, + Compact: 15, + } + var el2 = el + var expected = []DummyStruct{el, el2} + var actual = []DummyStruct{} + var decoder = NewDecoder(FromHex(input), 0) + decoder.Decode(&actual) + if !reflect.DeepEqual(actual, expected) { + t.Fatalf(`Decoder Slice Failure. Input %v, Output %v, Expected Output %v`, input, actual, expected) + } + } +} + +func TestDecoderStructures(t *testing.T) { + { + var input = "0x000102030414000102030480000000000000003c" + var expected = DummyStruct{ + Array: [5]byte{0, 1, 2, 3, 4}, + Slice: []byte{0, 1, 2, 3, 4}, + Primitive: 128, + Compact: 15, + } + var actual = DummyStruct{} + var decoder = NewDecoder(FromHex(input), 0) + decoder.Decode(&actual) + if !reflect.DeepEqual(actual, expected) { + t.Fatalf(`Decoder Structure. Output %v, Expected Output %v`, actual, expected) + } + } + + { + // Method ref/pointer struct + pointer method + var expected = DummyStruct2{ + value: uint32(0xbeef), + } + var input = Encoder.Encode(&expected) + var actual = DummyStruct2{} + var decoder = NewDecoder(FromHex(input), 0) + decoder.Decode(&actual) + if !reflect.DeepEqual(actual, expected) { + t.Fatalf(`Decoder Structure. Output %v, Expected Output %v`, actual, expected) + } + } +} diff --git a/primitives/scale_encoder.go b/primitives/scale_encoder.go new file mode 100644 index 0000000..e6cda05 --- /dev/null +++ b/primitives/scale_encoder.go @@ -0,0 +1,260 @@ +package primitives + +import ( + "fmt" + "math/big" + "math/bits" + "reflect" + + SType "github.com/itering/scale.go/types" + "github.com/itering/scale.go/utiles/uint128" +) + +type encoderT struct{} + +var Encoder encoderT + +// Fixed arrays +func (encoderT) array(value reflect.Value, dest *string) bool { + len := uint32(value.Len()) + if len == 0 { + return true + } + + // Lets see if we can encode the element, if not we bail out + tmp := "" + firstElement := value.Index(0) + if !Encoder.EncodeTo(firstElement.Interface(), &tmp) { + return false + } + + for i := 0; i < int(len); i++ { + if !Encoder.EncodeTo(value.Index(i).Interface(), dest) { + return false + } + } + + return true +} + +// Dynamic arrays +func (encoderT) slice(value reflect.Value, dest *string) bool { + len := uint32(value.Len()) + if len == 0 { + Encoder.EncodeTo(CompactU32{Value: 0}, dest) + return true + } + + // Lets see if we can encode the element, if not we bail out + tmp := "" + firstElement := value.Index(0) + if !Encoder.EncodeTo(firstElement.Interface(), &tmp) { + return false + } + + Encoder.EncodeTo(CompactU32{Value: len}, dest) + for i := 0; i < int(len); i++ { + if !Encoder.EncodeTo(value.Index(i).Interface(), dest) { + return false + } + } + + return true +} + +func (encoderT) callMethod(value reflect.Value, dest *string) bool { + methodName := "EncodeTo" + method := value.MethodByName(methodName) + + if !method.IsValid() { + return false + } + + args := []reflect.Value{reflect.ValueOf(dest)} + var _ = method.Call(args) + + return true + +} + +func (encoderT) structureFields(value reflect.Value, dest *string) bool { + valueType := value.Type() + + for i := 0; i < valueType.NumField(); i++ { + field := valueType.Field(i) + scaleTag := field.Tag.Get("scale") + if scaleTag == "ignore" { + continue + } + + isCompact := scaleTag == "compact" + fieldValue := value.Field(i) + if !Encoder.encodeToInner(fieldValue, dest, isCompact) { + return false + } + } + + return true +} + +func (encoderT) structure(value reflect.Value, dest *string) bool { + // See if there is a method that doesn't need a pointer + if Encoder.callMethod(value, dest) { + return true + } + + ptrValue := reflect.New(value.Type()) + ptrValue.Elem().Set(value) // Copy the original value into the pointer + + // See if there is a method that needs a pointer + if Encoder.callMethod(ptrValue, dest) { + return true + } + + // See if we can encode all the fields + return Encoder.structureFields(value, dest) +} + +func (encoderT) pointer(value reflect.Value, dest *string) bool { + if value.Kind() != reflect.Ptr { + return false + } + + if Encoder.callMethod(value, dest) { + return true + } + + return false +} + +func (encoderT) primitives(value reflect.Value, dest *string, isCompact bool) bool { + kind := value.Kind() + name := value.Type().Name() + if !isCompact { + if kind == reflect.Bool { + genericEncodeTo("bool", value.Interface(), dest) + return true + } + if kind == reflect.Uint8 { + genericEncodeTo("u8", value.Interface(), dest) + return true + } + if kind == reflect.Uint16 { + genericEncodeTo("u16", value.Interface(), dest) + return true + } + if kind == reflect.Uint32 { + genericEncodeTo("u32", value.Interface(), dest) + return true + } + if kind == reflect.Uint64 { + genericEncodeTo("u64", value.Interface(), dest) + return true + } + if name == "Uint128" { + genericEncodeTo("u128", value.Interface().(uint128.Uint128).String(), dest) + return true + } + } else { + if kind == reflect.Uint32 { + val := value.Interface().(uint32) + if val <= 1073741823 { + genericEncodeTo("Compact", val, dest) + return true + } + Encoder.EncodeTo(uint8(0b11), dest) + Encoder.EncodeTo(uint32(val), dest) + return true + } + if kind == reflect.Uint64 { + val := value.Interface().(uint64) + if val <= 1073741823 { + genericEncodeTo("Compact", uint128.From64(val).String(), dest) + return true + } + + leadingZeros := bits.LeadingZeros64(val) + bytesNeeded := 8 - leadingZeros/8 + midRes := uint8(0b11) + uint8(((bytesNeeded - 4) << 2)) + Encoder.EncodeTo(uint8(midRes), dest) + + v := val + for i := 0; i < bytesNeeded; i++ { + Encoder.EncodeTo(uint8(v), dest) + v = v >> 8 + } + return true + } + if name == "Uint128" { + val := value.Interface().(uint128.Uint128) + maxVal := uint128.From64(1073741823) + if val.Cmp(maxVal) != 1 { + genericEncodeTo("Compact", val.String(), dest) + return true + } + + leadingZeros := leadingZeros(val.Big(), 128) + bytesNeeded := 16 - leadingZeros/8 + midRes := uint8(0b11) + uint8(((bytesNeeded - 4) << 2)) + Encoder.EncodeTo(uint8(midRes), dest) + + v := val + for i := 0; i < bytesNeeded; i++ { + b := v.Big().Uint64() & 0xFF + Encoder.EncodeTo(uint8(b), dest) + v = v.Rsh(8) + } + return true + } + } + + return false +} + +func (encoderT) Encode(value interface{}) string { + encoded := "" + Encoder.EncodeTo(value, &encoded) + return encoded +} + +func (encoderT) EncodeTo(value interface{}, dest *string) bool { + valueOf := reflect.ValueOf(value) + return Encoder.encodeToInner(valueOf, dest, false) +} + +func (encoderT) encodeToInner(value reflect.Value, dest *string, isCompact bool) bool { + kind := value.Kind() + name := value.Type().Name() + + if Encoder.primitives(value, dest, isCompact) { + return true + } + + switch kind { + case reflect.Array: + return Encoder.array(value, dest) + case reflect.Slice: + return Encoder.slice(value, dest) + case reflect.Struct: + return Encoder.structure(value, dest) + case reflect.Pointer: + return Encoder.encodeToInner(value.Elem(), dest, isCompact) + default: + panic(fmt.Sprintf(`Unknown Type. Name: %v, Kind: %v`, name, kind)) + } +} + +func leadingZeros(x *big.Int, totalBits int) int { + if x.Sign() == 0 { // Handle zero case + return totalBits + } + return totalBits - x.BitLen() +} + +func (encoderT) FixedArrayTo(value []byte, dest *string) { + *dest = *dest + ToHex(value[:]) +} + +func genericEncodeTo(typeString string, value interface{}, dest *string) { + *dest += SType.Encode(typeString, value) +} diff --git a/primitives/scale_encoder_test.go b/primitives/scale_encoder_test.go new file mode 100644 index 0000000..baa34bc --- /dev/null +++ b/primitives/scale_encoder_test.go @@ -0,0 +1,436 @@ +package primitives + +import ( + "math/big" + "testing" + + "github.com/itering/scale.go/utiles/uint128" +) + +func TestEncoderBool(t *testing.T) { + var testParameters = map[bool]string{} + // Min + testParameters[false] = "0x00" + // Max + testParameters[true] = "0x01" + + for key, expected := range testParameters { + { + var actual = "0x" + Encoder.Encode(key) + if actual != expected { + t.Fatalf(`Encoder Bool Failure. Input %v, Output %v, Expected Output %v`, key, actual, expected) + } + } + { + var actual = "0x" + Encoder.EncodeTo(key, &actual) + if actual != expected { + t.Fatalf(`Encoder Bool Failure. Input %v, Output %v, Expected Output %v`, key, actual, expected) + } + } + } +} + +func TestEncoderUint8(t *testing.T) { + var testParameters = map[uint8]string{} + // Min + testParameters[0] = "0x00" + // Min + 1 + testParameters[1] = "0x01" + // Mid + testParameters[128] = "0x80" + // Max - 1 + testParameters[254] = "0xfe" + // Max + testParameters[255] = "0xff" + + for key, expected := range testParameters { + { + var actual = "0x" + Encoder.Encode(key) + if actual != expected { + t.Fatalf(`Encoder U8 Failure. Input %v, Output %v, Expected Output %v`, key, actual, expected) + } + } + { + var actual = "0x" + Encoder.EncodeTo(key, &actual) + if actual != expected { + t.Fatalf(`Encoder U8 Failure. Input %v, Output %v, Expected Output %v`, key, actual, expected) + } + } + } +} + +func TestEncoderUint16(t *testing.T) { + var testParameters = map[uint16]string{} + // Min + testParameters[0] = "0x0000" + // Min + 1 + testParameters[1] = "0x0100" + // Mid + testParameters[32768] = "0x0080" + // Max - 1 + testParameters[65534] = "0xfeff" + // Max + testParameters[65535] = "0xffff" + + for key, expected := range testParameters { + { + var actual = "0x" + Encoder.Encode(key) + if actual != expected { + t.Fatalf(`Encoder U16 Failure. Input %v, Output %v, Expected Output %v`, key, actual, expected) + } + } + { + var actual = "0x" + Encoder.EncodeTo(key, &actual) + if actual != expected { + t.Fatalf(`Encoder U16 Failure. Input %v, Output %v, Expected Output %v`, key, actual, expected) + } + } + } +} + +func TestEncoderUint32(t *testing.T) { + var testParameters = map[uint32]string{} + // Min + testParameters[0] = "0x00000000" + // Min + 1 + testParameters[1] = "0x01000000" + // Mid + testParameters[2147483648] = "0x00000080" + // Max - 1 + testParameters[4294967294] = "0xfeffffff" + // Max + testParameters[4294967295] = "0xffffffff" + + for key, expected := range testParameters { + { + var actual = "0x" + Encoder.Encode(key) + if actual != expected { + t.Fatalf(`Encoder U32 Failure. Input %v, Output %v, Expected Output %v`, key, actual, expected) + } + } + { + var actual = "0x" + Encoder.EncodeTo(key, &actual) + if actual != expected { + t.Fatalf(`Encoder U32 Failure. Input %v, Output %v, Expected Output %v`, key, actual, expected) + } + } + } +} + +func TestEncoderUint64(t *testing.T) { + var testParameters = map[uint64]string{} + // Min + testParameters[0] = "0x0000000000000000" + // Min + 1 + testParameters[1] = "0x0100000000000000" + // Mid + testParameters[9223372036854775807] = "0xffffffffffffff7f" + // Max - 1 + testParameters[18446744073709551614] = "0xfeffffffffffffff" + // Max + testParameters[18446744073709551615] = "0xffffffffffffffff" + + for key, expected := range testParameters { + { + var actual = "0x" + Encoder.Encode(key) + if actual != expected { + t.Fatalf(`Encoder U64 Failure. Input %v, Output %v, Expected Output %v`, key, actual, expected) + } + } + { + var actual = "0x" + Encoder.EncodeTo(key, &actual) + if actual != expected { + t.Fatalf(`Encoder U64 Failure. Input %v, Output %v, Expected Output %v`, key, actual, expected) + } + } + } +} + +func TestEncoderUint128(t *testing.T) { + var testParameters = map[uint128.Uint128]string{} + // Min + var res0, _ = new(big.Int).SetString("0", 10) + testParameters[uint128.FromBig(res0)] = "0x00000000000000000000000000000000" + // Min + 1 + var res1, _ = new(big.Int).SetString("1", 10) + testParameters[uint128.FromBig(res1)] = "0x01000000000000000000000000000000" + var res2, _ = new(big.Int).SetString("9223372036854775807", 10) + testParameters[uint128.FromBig(res2)] = "0xffffffffffffff7f0000000000000000" + var res7, _ = new(big.Int).SetString("18446744073709551615", 10) + testParameters[uint128.FromBig(res7)] = "0xffffffffffffffff0000000000000000" + var res8, _ = new(big.Int).SetString("18446744073709551616", 10) + testParameters[uint128.FromBig(res8)] = "0x00000000000000000100000000000000" + + for key, expected := range testParameters { + { + var actual = "0x" + Encoder.Encode(key) + if actual != expected { + t.Fatalf(`Encoder U128 Failure. Input %v, Output %v, Expected Output %v`, key, actual, expected) + } + } + { + var actual = "0x" + Encoder.EncodeTo(key, &actual) + if actual != expected { + t.Fatalf(`Encoder U128 Failure. Input %v, Output %v, Expected Output %v`, key, actual, expected) + } + } + } +} + +func TestEncoderCompactUint32(t *testing.T) { + var testParameters = map[uint32]string{} + // Min + testParameters[0] = "0x00" + // Min + 1 + testParameters[1] = "0x04" + // Mid + testParameters[2147483648] = "0x0300000080" + // Max - 1 + testParameters[4294967294] = "0x03feffffff" + // Max + testParameters[4294967295] = "0x03ffffffff" + + for key, expected := range testParameters { + { + var actual = "0x" + Encoder.Encode(CompactU32{Value: key}) + if actual != expected { + t.Fatalf(`Encoder U32 Failure. Input %v, Output %v, Expected Output %v`, key, actual, expected) + } + } + { + var actual = "0x" + Encoder.EncodeTo(CompactU32{Value: key}, &actual) + if actual != expected { + t.Fatalf(`Encoder U32 Failure. Input %v, Output %v, Expected Output %v`, key, actual, expected) + } + } + } +} + +func TestEncoderCompactUint64(t *testing.T) { + var testParameters = map[uint64]string{} + // Min + testParameters[0] = "0x00" + // Min + 1 + testParameters[1] = "0x04" + // Mid + testParameters[9223372036854775807] = "0x13ffffffffffffff7f" + // Max - 1 + testParameters[18446744073709551614] = "0x13feffffffffffffff" + // Max + testParameters[18446744073709551615] = "0x13ffffffffffffffff" + + for key, expected := range testParameters { + { + var actual = "0x" + Encoder.Encode(CompactU64{Value: key}) + if actual != expected { + t.Fatalf(`Encoder U64 Failure. Input %v, Output %v, Expected Output %v`, key, actual, expected) + } + } + { + var actual = "0x" + Encoder.EncodeTo(CompactU64{Value: key}, &actual) + if actual != expected { + t.Fatalf(`Encoder U64 Failure. Input %v, Output %v, Expected Output %v`, key, actual, expected) + } + } + } +} + +func TestEncoderCompactUint128(t *testing.T) { + var testParameters = map[uint128.Uint128]string{} + // Min + var res0, _ = new(big.Int).SetString("0", 10) + testParameters[uint128.FromBig(res0)] = "0x00" + // Min + 1 + var res1, _ = new(big.Int).SetString("1", 10) + testParameters[uint128.FromBig(res1)] = "0x04" + var res2, _ = new(big.Int).SetString("9223372036854775807", 10) + testParameters[uint128.FromBig(res2)] = "0x13ffffffffffffff7f" + var res7, _ = new(big.Int).SetString("18446744073709551615", 10) + testParameters[uint128.FromBig(res7)] = "0x13ffffffffffffffff" + var res8, _ = new(big.Int).SetString("18446744073709551616", 10) + testParameters[uint128.FromBig(res8)] = "0x17000000000000000001" + + for key, expected := range testParameters { + { + var actual = "0x" + Encoder.Encode(CompactU128{Value: key}) + if actual != expected { + t.Fatalf(`Encoder U128 Failure. Input %v, Output %v, Expected Output %v`, key, actual, expected) + } + } + { + var actual = "0x" + Encoder.EncodeTo(CompactU128{Value: key}, &actual) + if actual != expected { + t.Fatalf(`Encoder U128 Failure. Input %v, Output %v, Expected Output %v`, key, actual, expected) + } + } + } +} + +type DummyStruct struct { + Array [5]byte + Slice []byte + Primitive uint64 + Compact uint32 `scale:"compact"` +} + +type DummyStruct2 struct { + value uint32 +} + +func (this DummyStruct2) EncodeTo(dest *string) { + *dest = "Success" +} + +func (this *DummyStruct2) Decode(decoder *Decoder) error { + this.value = uint32(0xbeef) + return nil +} + +type DummyStruct3 struct { + value uint32 +} + +func (this *DummyStruct3) EncodeTo(dest *string) { + *dest = "Success" +} + +func TestEncoderArray(t *testing.T) { + var expected = "0x0001020304" + // Primitives + { + var array = [5]byte{0, 1, 2, 3, 4} + var actual = "0x" + Encoder.Encode(array) + if actual != expected { + t.Fatalf(`Encoder Fixed Array Primitives. Input %v, Output %v, Expected Output %v`, array, actual, expected) + } + + var actual2 = "0x" + Encoder.EncodeTo(array, &actual2) + if actual != expected { + t.Fatalf(`Encoder Fixed Array Primitives. Input %v, Output %v, Expected Output %v`, array, actual, expected) + } + } + + // Structures + { + var expected = "0x000102030414000102030480000000000000003c000102030414000102030480000000000000003c" + var el = DummyStruct{ + Array: [5]byte{0, 1, 2, 3, 4}, + Slice: []byte{0, 1, 2, 3, 4}, + Primitive: 128, + Compact: 15, + } + var el2 = el + var array = [2]DummyStruct{el, el2} + var actual = "0x" + Encoder.Encode(array) + if actual != expected { + t.Fatalf(`Encoder Fixed Array Struct. Output %v, Expected Output %v`, actual, expected) + } + + var actual2 = "0x" + Encoder.EncodeTo(array, &actual2) + if actual != expected { + t.Fatalf(`Encoder Fixed Array Struct. Output %v, Expected Output %v`, actual, expected) + } + } +} + +func TestEncoderSlice(t *testing.T) { + var expected = "0x140001020304" + // Primitives + { + var array = []byte{0, 1, 2, 3, 4} + var actual = "0x" + Encoder.Encode(array) + if actual != expected { + t.Fatalf(`Encoder Fixed Array Primitives. Input %v, Output %v, Expected Output %v`, array, actual, expected) + } + + var actual2 = "0x" + Encoder.EncodeTo(array, &actual2) + if actual != expected { + t.Fatalf(`Encoder Fixed Array Primitives. Input %v, Output %v, Expected Output %v`, array, actual, expected) + } + } + + // Structures + { + var expected = "0x08000102030414000102030480000000000000003c000102030414000102030480000000000000003c" + var el = DummyStruct{ + Array: [5]byte{0, 1, 2, 3, 4}, + Slice: []byte{0, 1, 2, 3, 4}, + Primitive: 128, + Compact: 15, + } + var el2 = el + var array = []DummyStruct{el, el2} + var actual = "0x" + Encoder.Encode(array) + if actual != expected { + t.Fatalf(`Encoder Slice Struct. Output %v, Expected Output %v`, actual, expected) + } + + var actual2 = "0x" + Encoder.EncodeTo(array, &actual2) + if actual != expected { + t.Fatalf(`Encoder Slice Struct. Output %v, Expected Output %v`, actual, expected) + } + } +} + +func TestEncoderStructures(t *testing.T) { + { + var expected = "0x000102030414000102030480000000000000003c" + var el = DummyStruct{ + Array: [5]byte{0, 1, 2, 3, 4}, + Slice: []byte{0, 1, 2, 3, 4}, + Primitive: 128, + Compact: 15, + } + var actual = "0x" + Encoder.Encode(el) + if actual != expected { + t.Fatalf(`Encoder Structure. Output %v, Expected Output %v`, actual, expected) + } + + var actual2 = "0x" + Encoder.EncodeTo(el, &actual2) + if actual != expected { + t.Fatalf(`Encoder Structure. Output %v, Expected Output %v`, actual, expected) + } + } + + { + // Method ref/pointer struct + ref method + var expected = "Success" + var actual1 = Encoder.Encode(DummyStruct2{}) + if actual1 != expected { + t.Fatalf(`Encoder Structure Method. Output %v, Expected Output %v`, actual1, expected) + } + + var actual2 = Encoder.Encode(&DummyStruct2{}) + if actual2 != expected { + t.Fatalf(`Encoder Structure Method. Output %v, Expected Output %v`, actual2, expected) + } + } + + { + // Method ref/pointer struct + pointer method + var expected = "Success" + var actual1 = Encoder.Encode(DummyStruct3{}) + if actual1 != expected { + t.Fatalf(`Encoder Structure Method. Output %v, Expected Output %v`, actual1, expected) + } + + var actual2 = Encoder.Encode(&DummyStruct3{}) + if actual2 != expected { + t.Fatalf(`Encoder Structure Method. Output %v, Expected Output %v`, actual2, expected) + } + } +} diff --git a/primitives/scale_hex.go b/primitives/scale_hex.go new file mode 100644 index 0000000..9cf6e29 --- /dev/null +++ b/primitives/scale_hex.go @@ -0,0 +1,17 @@ +package primitives + +import ( + SUtiles "github.com/itering/scale.go/utiles" +) + +func ToHex(arr []byte) string { + return SUtiles.BytesToHex(arr) +} + +func FromHex(arr string) []byte { + return SUtiles.HexToBytes(arr) +} + +func ToHexWith0x(arr []byte) string { + return "0x" + ToHex(arr) +} diff --git a/primitives/scale_types.go b/primitives/scale_types.go new file mode 100644 index 0000000..822d3e3 --- /dev/null +++ b/primitives/scale_types.go @@ -0,0 +1,93 @@ +package primitives + +import ( + "github.com/itering/scale.go/utiles/uint128" +) + +type Option[T any] struct { + value T + isSet bool +} + +func (this Option[T]) EncodeTo(dest *string) { + if !this.isSet { + Encoder.EncodeTo(uint8(0), dest) + return + } + Encoder.EncodeTo(uint8(1), dest) + Encoder.EncodeTo(this.value, dest) +} + +func (this *Option[T]) Decode(decoder *Decoder) error { + hasValue := uint8(0) + if err := decoder.Decode(&hasValue); err != nil { + return err + } + if hasValue == 1 { + this.isSet = true + if err := decoder.Decode(&this.value); err != nil { + return err + } + } else { + this.isSet = false + } + + return nil +} + +func (this *Option[T]) Set(value T) { + this.value = value + this.isSet = true +} + +func (this Option[T]) IsSome() bool { + return this.isSet +} + +func (this Option[T]) IsNone() bool { + return !this.isSet +} + +func (this Option[T]) Unwrap() T { + if this.isSet == false { + panic("Option is not set.") + } + return this.value +} + +func (this Option[T]) UnwrapOrDefault() T { + if this.isSet == false { + var t T + return t + } + return this.value +} + +func (this Option[T]) Unwrap0rElse(elseValue T) T { + if this.isSet == false { + return elseValue + } + return this.value +} + +func NewSome[T any](value T) Option[T] { + option := Option[T]{} + option.Set(value) + return option +} + +func NewNone[T any]() Option[T] { + return Option[T]{} +} + +type CompactU32 struct { + Value uint32 `scale:"compact"` +} + +type CompactU64 struct { + Value uint64 `scale:"compact"` +} + +type CompactU128 struct { + Value uint128.Uint128 `scale:"compact"` +} diff --git a/primitives/signature.go b/primitives/signature.go new file mode 100644 index 0000000..be1dbbb --- /dev/null +++ b/primitives/signature.go @@ -0,0 +1,85 @@ +package primitives + +import ( + "errors" + "fmt" +) + +// Do not change the order of field members. +type MultiSignature struct { + Ed25519 Option[H512] + Sr25519 Option[H512] + Ecdsa Option[H520] +} + +func emptyMultiSignature() MultiSignature { + return MultiSignature{ + Ed25519: NewNone[H512](), + Sr25519: NewNone[H512](), + Ecdsa: NewNone[H520](), + } +} + +func NewMultiSignatureEd(value H512) MultiSignature { + signature := emptyMultiSignature() + signature.Ed25519 = NewSome(value) + return signature +} + +func NewMultiSignatureSr(value H512) MultiSignature { + signature := emptyMultiSignature() + signature.Sr25519 = NewSome(value) + return signature +} + +func NewMultiSignatureEcdsa(value H520) MultiSignature { + signature := emptyMultiSignature() + signature.Ecdsa = NewSome(value) + return signature +} + +func (this *MultiSignature) EncodeTo(dest *string) { + if this.Ed25519.IsSome() { + Encoder.EncodeTo(uint8(0), dest) + Encoder.EncodeTo(this.Ed25519.Unwrap(), dest) + } else if this.Sr25519.IsSome() { + Encoder.EncodeTo(uint8(1), dest) + Encoder.EncodeTo(this.Sr25519.Unwrap(), dest) + } else if this.Ecdsa.IsSome() { + Encoder.EncodeTo(uint8(2), dest) + Encoder.EncodeTo(this.Ecdsa.Unwrap(), dest) + } else { + panic("Something Went Wrong with MultiSignature EncodeTo") + } + +} + +func (this *MultiSignature) Decode(decoder *Decoder) error { + result := emptyMultiSignature() + variantIndex := uint8(0) + decoder.Decode(&variantIndex) + if variantIndex == 0 { + value := H512{} + if err := decoder.Decode(&value); err != nil { + return err + } + result.Ed25519 = NewSome(value) + } else if variantIndex == 1 { + value := H512{} + if err := decoder.Decode(&value); err != nil { + return err + } + result.Sr25519 = NewSome(value) + } else if variantIndex == 2 { + value := H520{} + if err := decoder.Decode(&value); err != nil { + return err + } + result.Ecdsa = NewSome(value) + } else { + return errors.New(fmt.Sprintf(`MultiSignature Decode failure. Unknown Variant index: %v`, variantIndex)) + } + + *this = result + return nil +} diff --git a/run_tests.sh b/run_tests.sh new file mode 100755 index 0000000..d54352e --- /dev/null +++ b/run_tests.sh @@ -0,0 +1,2 @@ +cd primitives +go test . \ No newline at end of file diff --git a/sdk.go b/sdk.go new file mode 100644 index 0000000..b5e69dc --- /dev/null +++ b/sdk.go @@ -0,0 +1,51 @@ +package main + +import ( + Complex "go-sdk/complex" + DA "go-sdk/metadata/pallets/data_availability" + Prim "go-sdk/primitives" +) + +type SDK struct { + Client *Complex.Client + Tx Transactions +} + +func NewSDK(endpoint string) SDK { + var client = Complex.NewClient(endpoint) + client.InitMetadata(Prim.NewNone[Prim.H256]()) + return SDK{ + Client: client, + Tx: newTransactions(client), + } +} + +func NewSDK2(endpoint string) SDK { + var client = Complex.NewClient(endpoint) + return SDK{ + Client: client, + Tx: newTransactions(client), + } +} + +type Transactions struct { + DataAvailability DataAvailabilityTx +} + +func newTransactions(client *Complex.Client) Transactions { + var da = DataAvailabilityTx{Client: client} + return Transactions{ + DataAvailability: da, + } +} + +type DataAvailabilityTx struct { + Client *Complex.Client +} + +func (this *DataAvailabilityTx) SubmitData(data []byte) Complex.Transaction { + var call = DA.CallSubmitData{ + Data: data, + } + return Complex.NewTransaction(this.Client, call.ToPayload()) +} diff --git a/src/config/config.go b/src/config/config.go deleted file mode 100644 index 1915384..0000000 --- a/src/config/config.go +++ /dev/null @@ -1,59 +0,0 @@ -package config - -import ( - "encoding/json" - "flag" - "fmt" - "io" - "log" - "os" -) - -type Config struct { - Seed string `json:"seed"` - ApiURL string `json:"api_url"` - Size int `json:"size"` - AppID int `json:"app_id"` - Dest string `json:"dest"` - Amount uint64 `json:"amount"` - SessionKeys string `json:"session_keys"` -} - -func (c *Config) GetConfig(configFileName string) error { - jsonFile, err := os.Open(configFileName) - if err != nil { - return err - } - defer jsonFile.Close() - - byteValue, err := io.ReadAll(jsonFile) - if err != nil { - return err - } - - err = json.Unmarshal(byteValue, c) - if err != nil { - return err - } - - return nil -} - -func LoadConfig() (*Config, error) { - var configJSON string - flag.StringVar(&configJSON, "config", "", "config json file") - flag.Parse() - - if configJSON == "" { - log.Println("No config file provided. Exiting...") - os.Exit(0) - } - - var config Config - err := config.GetConfig(configJSON) - if err != nil { - return nil, fmt.Errorf("cannot get config: %v", err) - } - - return &config, nil -} diff --git a/src/extrinsic/era.go b/src/extrinsic/era.go deleted file mode 100644 index 7e3e1e7..0000000 --- a/src/extrinsic/era.go +++ /dev/null @@ -1,163 +0,0 @@ -package extrinsic - -import ( - "errors" - "math" - "strconv" - - "github.com/centrifuge/go-substrate-rpc-client/v4/scale" - "github.com/centrifuge/go-substrate-rpc-client/v4/types" -) - -// ExtrinsicEra indicates either a mortal or immortal extrinsic -type ExtrinsicEra struct { - IsImmortalEra bool - // AsImmortalEra ImmortalEra - IsMortalEra bool - AsMortalEra MortalEra -} - -func (e *ExtrinsicEra) Decode(decoder scale.Decoder) error { - first, err := decoder.ReadOneByte() - if err != nil { - return err - } - - if first == 0 { - e.IsImmortalEra = true - return nil - } - - second, err := decoder.ReadOneByte() - if err != nil { - return err - } - - encoded := uint64(first) + (uint64(second) << 8) - period := 2 << (encoded % (1 << 4)) - quantizeFactor := period >> 12 - - if quantizeFactor <= 1 { - quantizeFactor = 1 - } - - phase := (encoded >> 4) * uint64(quantizeFactor) - - if period >= 4 && phase < uint64(period) { - e.IsMortalEra = true - e.AsMortalEra = MortalEra{ - First: types.U64(period), - Second: types.U64(phase), - } - return nil - } - - return errors.New("invalid era") -} - -func (e ExtrinsicEra) Encode(encoder scale.Encoder) error { - if e.IsImmortalEra { - return encoder.PushByte(0) - } - - // let quantize_factor = (*period as u64 >> 12).max(1); - quantizeFactor := e.AsMortalEra.First >> 12 - - if quantizeFactor <= 1 { - quantizeFactor = 1 - } - - // let encoded = (period.trailing_zeros() - 1).max(1).min(15) as u16 | - // ((phase / quantize_factor) << 4) as u16; - trailingZeroes := getTrailingZeroes(e.AsMortalEra.First) - 1 - - if trailingZeroes <= 1 { - trailingZeroes = 1 - } - - if trailingZeroes >= 15 { - trailingZeroes = 15 - } - - r := types.U16((e.AsMortalEra.Second / quantizeFactor) << 4) - - encoded := trailingZeroes | r - - // encoded.encode_to(output); - return encoder.Encode(encoded) -} - -// MortalEra for an extrinsic, indicating period and phase -type MortalEra struct { - First types.U64 - Second types.U64 -} - -func NewMortalEra(currentBlock types.BlockNumber, blockHashCount types.U64) MortalEra { - // BlockHashCount::get().checked_next_power_of_two().map(|c| c / 2).unwrap_or(2) as u64; - np := getNextPowerOfTwo(blockHashCount, 2) - - var npb types.U64 - - if np > 2 { - npb = np / 2 - } - - // let period = period.checked_next_power_of_two().unwrap_or(1 << 16).max(4).min(1 << 16); - period := getNextPowerOfTwo(npb, 1<<16) - - if period <= 4 { - period = 4 - } - - if period >= 1<<16 { - period = 1 << 16 - } - - // let phase = current % period; - phase := types.U64(currentBlock) % period - - // let quantize_factor = (period >> 12).max(1); - quantizeFactor := period >> 12 - - if quantizeFactor <= 1 { - quantizeFactor = 1 - } - - // let quantized_phase = phase / quantize_factor * quantize_factor; - quantizedPhase := phase / quantizeFactor * quantizeFactor - - return MortalEra{period, quantizedPhase} -} - -func getNextPowerOfTwo(n types.U64, def types.U64) types.U64 { - bn := strconv.FormatInt(int64(n), 2) - numBits := len(bn) - - if (1 << (numBits - 1)) == n { - return n - } - - res := uint(1 << numBits) - - if res > math.MaxUint64 { - return def - } - - return types.U64(res) -} - -func getTrailingZeroes(n types.U64) types.U16 { - var count types.U16 - - for n > 0 { - if n%2 == 1 { - break - } - - n = n / 2 - count++ - } - - return count -} diff --git a/src/extrinsic/extrinsic.go b/src/extrinsic/extrinsic.go deleted file mode 100644 index c1c9a84..0000000 --- a/src/extrinsic/extrinsic.go +++ /dev/null @@ -1,262 +0,0 @@ -package extrinsic - -import ( - "bytes" - "encoding/json" - "fmt" - "math/big" - "strings" - - "github.com/centrifuge/go-substrate-rpc-client/v4/scale" - "github.com/centrifuge/go-substrate-rpc-client/v4/signature" - "github.com/centrifuge/go-substrate-rpc-client/v4/types" - "github.com/centrifuge/go-substrate-rpc-client/v4/types/codec" -) - -type SignatureOptions struct { - Era ExtrinsicEra - Nonce types.UCompact - Tip types.UCompact - SpecVersion types.U32 - GenesisHash types.Hash - BlockHash types.Hash - AppID types.UCompact - TransactionVersion types.U32 -} -type ExtrinsicSignatureV4 struct { - Signer types.MultiAddress - Signature types.MultiSignature - Era ExtrinsicEra // extra via system::CheckEra - Nonce types.UCompact // extra via system::CheckNonce (Compact where Index is u32)) - Tip types.UCompact // extra via balances::TakeFees (Compact where Balance is u128)) - AppID types.UCompact // Avail specific AppID -} - -const ( - ExtrinsicBitSigned = 0x80 - ExtrinsicBitUnsigned = 0 - ExtrinsicUnmaskVersion = 0x7f - ExtrinsicDefaultVersion = 1 - ExtrinsicVersionUnknown = 0 // v0 is unknown - ExtrinsicVersion1 = 1 - ExtrinsicVersion2 = 2 - ExtrinsicVersion3 = 3 - ExtrinsicVersion4 = 4 -) - -// Extrinsic is a piece of Args bundled into a block that expresses something from the "external" (i.e. off-chain) -// world. There are, broadly speaking, two types of extrinsic: transactions (which tend to be signed) and -// inherents (which don't). -type Extrinsic struct { - // Version is the encoded version flag (which encodes the raw transaction version and signing information in one byte) - Version byte - // Signature is the ExtrinsicSignatureV4, it's presence depends on the Version flag - Signature ExtrinsicSignatureV4 - // Method is the call this extrinsic wraps - Method types.Call -} - -// NewExtrinsic creates a new Extrinsic from the provided Call -func NewExtrinsic(c types.Call) Extrinsic { - return Extrinsic{ - Version: ExtrinsicVersion4, - Method: c, - } -} - -// UnmarshalJSON fills Extrinsic with the JSON encoded byte array given by bz -func (e *Extrinsic) UnmarshalJSON(bz []byte) error { - var tmp string - if err := json.Unmarshal(bz, &tmp); err != nil { - return err - } - - // HACK 11 Jan 2019 - before https://github.com/paritytech/substrate/pull/1388 - // extrinsics didn't have the length, cater for both approaches. This is very - // inconsistent with any other `Vec` implementation - var l types.UCompact - err := codec.DecodeFromHex(tmp, &l) - if err != nil { - return err - } - - prefix, err := codec.EncodeToHex(l) - if err != nil { - return err - } - - // determine whether length prefix is there - if strings.HasPrefix(tmp, prefix) { - return codec.DecodeFromHex(tmp, e) - } - - // not there, prepend with compact encoded length prefix - dec, err := codec.HexDecodeString(tmp) - if err != nil { - return err - } - length := types.NewUCompactFromUInt(uint64(len(dec))) - bprefix, err := codec.Encode(length) - if err != nil { - return err - } - bprefix = append(bprefix, dec...) - return codec.Decode(bprefix, e) -} - -// MarshalJSON returns a JSON encoded byte array of Extrinsic -func (e Extrinsic) MarshalJSON() ([]byte, error) { - s, err := codec.EncodeToHex(e) - if err != nil { - return nil, err - } - return json.Marshal(s) -} - -// IsSigned returns true if the extrinsic is signed -func (e Extrinsic) IsSigned() bool { - return e.Version&ExtrinsicBitSigned == ExtrinsicBitSigned -} - -// Type returns the raw transaction version (not flagged with signing information) -func (e Extrinsic) Type() uint8 { - return e.Version & ExtrinsicUnmaskVersion -} - -// Sign adds a signature to the extrinsic -func (e *Extrinsic) Sign(signer signature.KeyringPair, o SignatureOptions) error { - if e.Type() != ExtrinsicVersion4 { - return fmt.Errorf("unsupported extrinsic version: %v (isSigned: %v, type: %v)", e.Version, e.IsSigned(), e.Type()) - } - - mb, err := codec.Encode(e.Method) - if err != nil { - return err - } - - era := o.Era - if !o.Era.IsMortalEra { - era = ExtrinsicEra{IsImmortalEra: true} - } - - payload := ExtrinsicPayloadV3{ - Method: mb, - Era: era, - Nonce: o.Nonce, - Tip: o.Tip, - AppID: o.AppID, - SpecVersion: o.SpecVersion, - TransactionVersion: o.TransactionVersion, - GenesisHash: o.GenesisHash, - BlockHash: o.BlockHash, - } - - signerPubKey, err := types.NewMultiAddressFromAccountID(signer.PublicKey) - - if err != nil { - return err - } - - sig, err := payload.Sign(signer) - if err != nil { - return err - } - - extSig := ExtrinsicSignatureV4{ - Signer: signerPubKey, - Signature: types.MultiSignature{IsSr25519: true, AsSr25519: sig}, - Era: era, - Nonce: o.Nonce, - Tip: o.Tip, - AppID: o.AppID, - } - - e.Signature = extSig - - // mark the extrinsic as signed - e.Version |= ExtrinsicBitSigned - - return nil -} - -func (e *Extrinsic) Decode(decoder scale.Decoder) error { - // compact length encoding (1, 2, or 4 bytes) (may not be there for Extrinsics older than Jan 11 2019) - _, err := decoder.DecodeUintCompact() - if err != nil { - return err - } - - // version, signature bitmask (1 byte) - err = decoder.Decode(&e.Version) - if err != nil { - return err - } - - // signature - if e.IsSigned() { - if e.Type() != ExtrinsicVersion4 { - return fmt.Errorf("unsupported extrinsic version: %v (isSigned: %v, type: %v)", e.Version, e.IsSigned(), - e.Type()) - } - - err = decoder.Decode(&e.Signature) - if err != nil { - return err - } - } - - // call - err = decoder.Decode(&e.Method) - if err != nil { - return err - } - - return nil -} - -func (e Extrinsic) Encode(encoder scale.Encoder) error { - if e.Type() != ExtrinsicVersion4 { - return fmt.Errorf("unsupported extrinsic version: %v (isSigned: %v, type: %v)", e.Version, e.IsSigned(), - e.Type()) - } - - // create a temporary buffer that will receive the plain encoded transaction (version, signature (optional), - // method/call) - var bb = bytes.Buffer{} - tempEnc := scale.NewEncoder(&bb) - - // encode the version of the extrinsic - err := tempEnc.Encode(e.Version) - if err != nil { - return err - } - - // encode the signature if signed - if e.IsSigned() { - err = tempEnc.Encode(e.Signature) - if err != nil { - return err - } - } - - // encode the method - err = tempEnc.Encode(e.Method) - if err != nil { - return err - } - - // take the temporary buffer to determine length, write that as prefix - eb := bb.Bytes() - err = encoder.EncodeUintCompact(*big.NewInt(0).SetUint64(uint64(len(eb)))) - if err != nil { - return err - } - - // write the actual encoded transaction - err = encoder.Write(eb) - if err != nil { - return err - } - - return nil -} diff --git a/src/extrinsic/payload.go b/src/extrinsic/payload.go deleted file mode 100644 index 6229372..0000000 --- a/src/extrinsic/payload.go +++ /dev/null @@ -1,158 +0,0 @@ -package extrinsic - -import ( - "fmt" - - "github.com/centrifuge/go-substrate-rpc-client/v4/signature" - "github.com/centrifuge/go-substrate-rpc-client/v4/types" - "github.com/centrifuge/go-substrate-rpc-client/v4/types/codec" - "github.com/vedhavyas/go-subkey/scale" -) - -type ExtrinsicPayloadV3 struct { - Method types.BytesBare - Era ExtrinsicEra // extra via system::CheckEra - Nonce types.UCompact // extra via system::CheckNonce (Compact where Index is u32) - Tip types.UCompact // extra via balances::TakeFees (Compact where Balance is u128) - AppID types.UCompact - SpecVersion types.U32 // additional via system::CheckVersion - TransactionVersion types.U32 - GenesisHash types.Hash // additional via system::CheckGenesis - BlockHash types.Hash // additional via system::CheckEra -} - -// Sign the extrinsic payload with the given derivation path -func (e ExtrinsicPayloadV3) Sign(signer signature.KeyringPair) (types.Signature, error) { - b, err := codec.Encode(e) - if err != nil { - return types.Signature{}, err - } - - sig, err := signature.Sign(b, signer.URI) - return types.NewSignature(sig), err -} - -// Encode implements encoding for ExtrinsicPayloadV3, which just unwraps the bytes of ExtrinsicPayloadV3 without -// adding a compact length prefix -func (e ExtrinsicPayloadV3) Encode(encoder scale.Encoder) error { - err := encoder.Encode(e.Method) - if err != nil { - return err - } - - err = encoder.Encode(e.Era) - if err != nil { - return err - } - - err = encoder.Encode(e.Nonce) - if err != nil { - return err - } - - err = encoder.Encode(e.Tip) - if err != nil { - return err - } - - err = encoder.Encode(e.SpecVersion) - if err != nil { - return err - } - - err = encoder.Encode(e.GenesisHash) - if err != nil { - return err - } - - err = encoder.Encode(e.BlockHash) - if err != nil { - return err - } - err = encoder.Encode(e.AppID) - if err != nil { - return err - } - err = encoder.Encode(e.TransactionVersion) - if err != nil { - return err - } - - return nil -} - -// Decode does nothing and always returns an error. ExtrinsicPayloadV3 is only used for encoding, not for decoding -func (e *ExtrinsicPayloadV3) Decode(decoder scale.Decoder) error { - return fmt.Errorf("decoding of ExtrinsicPayloadV3 is not supported") -} - -type ExtrinsicPayloadV4 struct { - ExtrinsicPayloadV3 - TransactionVersion types.U32 - AppID types.UCompact -} - -// Sign the extrinsic payload with the given derivation path -func (e ExtrinsicPayloadV4) Sign(signer signature.KeyringPair) (types.Signature, error) { - b, err := codec.Encode(e) - if err != nil { - return types.Signature{}, err - } - - sig, err := signature.Sign(b, signer.URI) - return types.NewSignature(sig), err -} - -func (e ExtrinsicPayloadV4) Encode(encoder scale.Encoder) error { - err := encoder.Encode(e.Method) - if err != nil { - return err - } - - err = encoder.Encode(e.Era) - if err != nil { - return err - } - - err = encoder.Encode(e.Nonce) - if err != nil { - return err - } - - err = encoder.Encode(e.Tip) - if err != nil { - return err - } - - err = encoder.Encode(e.AppID) - if err != nil { - return err - } - - err = encoder.Encode(e.SpecVersion) - if err != nil { - return err - } - - err = encoder.Encode(e.TransactionVersion) - if err != nil { - return err - } - - err = encoder.Encode(e.GenesisHash) - if err != nil { - return err - } - - err = encoder.Encode(e.BlockHash) - if err != nil { - return err - } - - return nil -} - -// Decode does nothing and always returns an error. ExtrinsicPayloadV4 is only used for encoding, not for decoding -func (e *ExtrinsicPayloadV4) Decode(decoder scale.Decoder) error { - return fmt.Errorf("decoding of ExtrinsicPayloadV4 is not supported") -} diff --git a/src/header/header.go b/src/header/header.go deleted file mode 100644 index c9ebf92..0000000 --- a/src/header/header.go +++ /dev/null @@ -1,74 +0,0 @@ -package header - -import ( - avail "github.com/availproject/avail-go-sdk/src/sdk/types" - - "github.com/centrifuge/go-substrate-rpc-client/v4/scale" - "github.com/centrifuge/go-substrate-rpc-client/v4/types" -) - -type DataLookupIndexItem struct { - AppId avail.UCompact `json:"appId"` - Start avail.UCompact `json:"start"` -} -type DataLookup struct { - Size avail.UCompact `json:"size"` - Index []DataLookupIndexItem `json:"index"` -} - -type KateCommitment struct { - Rows avail.UCompact `json:"rows"` - Cols avail.UCompact `json:"cols"` - Commitment []types.U8 `json:"commitment"` - DataRoot types.Hash `json:"dataRoot"` -} - -type V3HeaderExtension struct { - AppLookup DataLookup `json:"appLookup"` - Commitment KateCommitment `json:"commitment"` -} - -type HeaderExtensionEnum struct { - V3 V3HeaderExtension `json:"V3"` -} - -type Header struct { - ParentHash types.Hash `json:"parentHash"` - Number types.BlockNumber `json:"number"` - StateRoot types.Hash `json:"stateRoot"` - ExtrinsicsRoot types.Hash `json:"extrinsicsRoot"` - Digest types.Digest `json:"digest"` - Extension HeaderExtensionEnum `json:"extension"` -} - -func (m HeaderExtensionEnum) Encode(encoder scale.Encoder) error { - var err, err1 error - - err = encoder.PushByte(2) - - if err != nil { - return err - } - err1 = encoder.Encode(m.V3) - if err1 != nil { - return err1 - } - return nil -} - -func (m *HeaderExtensionEnum) Decode(decoder scale.Decoder) error { - b, err := decoder.ReadOneByte() - - if err != nil { - return err - } - - if b == 2 { - err = decoder.Decode(&m.V3) - } - if err != nil { - return err - } - - return nil -} diff --git a/src/rpc/block.go b/src/rpc/block.go deleted file mode 100644 index 8b97e8c..0000000 --- a/src/rpc/block.go +++ /dev/null @@ -1,91 +0,0 @@ -package rpc - -import ( - "github.com/availproject/avail-go-sdk/src/extrinsic" - "github.com/availproject/avail-go-sdk/src/header" - - "github.com/centrifuge/go-substrate-rpc-client/v4/client" - "github.com/centrifuge/go-substrate-rpc-client/v4/types" -) - -type SignedBlock struct { - Block Block `json:"block"` - Justification types.Justification `json:"justification"` -} - -// Block encoded with header and extrinsics -type Block struct { - Header header.Header `json:"header"` - Extrinsics []extrinsic.Extrinsic -} - -// GetBlock returns the header and body of the relay chain block with the given hash -func GetAvailBlock(blockHash types.Hash, client1 client.Client) (*SignedBlock, error) { - return getBlock(&blockHash, client1) -} - -func GetAvailBlockLatest(client1 client.Client) (*SignedBlock, error) { - return getBlock(nil, client1) -} - -func getBlock(blockHash *types.Hash, client1 client.Client) (*SignedBlock, error) { - var SignedBlock SignedBlock - err := client.CallWithBlockHash(client1, &SignedBlock, "chain_getBlock", blockHash) - if err != nil { - return nil, err - } - return &SignedBlock, err -} - -func GetFinalizedHead(client client.Client) (types.Hash, error) { - var res string - - err := client.Call(&res, "chain_getFinalizedHead") - if err != nil { - return types.Hash{}, err - } - - return types.NewHashFromHexString(res) -} - -func getBlockHash(client client.Client, blockNumber *uint64) (types.Hash, error) { - var res string - var err error - - if blockNumber == nil { - err = client.Call(&res, "chain_getBlockHash") - } else { - err = client.Call(&res, "chain_getBlockHash", *blockNumber) - } - - if err != nil { - return types.Hash{}, err - } - - return types.NewHashFromHexString(res) -} - -func GetBlockHash(client client.Client, blockNumber uint64) (types.Hash, error) { - return getBlockHash(client, &blockNumber) -} - -func GetBlockHashLatest(client client.Client) (types.Hash, error) { - return getBlockHash(client, nil) -} - -func getHeader(client1 client.Client, blockHash *types.Hash) (*header.Header, error) { - var Header header.Header - err := client.CallWithBlockHash(client1, &Header, "chain_getHeader", blockHash) - if err != nil { - return nil, err - } - return &Header, err -} - -func GetHeaderLatest(client1 client.Client) (*header.Header, error) { - return getHeader(client1, nil) -} - -func GetHeader(client1 client.Client, blockHash types.Hash) (*header.Header, error) { - return getHeader(client1, &blockHash) -} diff --git a/src/rpc/kate.go b/src/rpc/kate.go deleted file mode 100644 index a9523d5..0000000 --- a/src/rpc/kate.go +++ /dev/null @@ -1,150 +0,0 @@ -package rpc - -import ( - "encoding/json" - "fmt" - "math/big" - "strings" - - "github.com/centrifuge/go-substrate-rpc-client/v4/types" -) - -const MaxCells = 10000 - -type Cell struct { - Row uint64 `json:"row"` - Col uint64 `json:"col"` -} - -func NewCell(row, col uint64) Cell { - return Cell{Row: row, Col: col} -} - -type GDataProof struct { - RawScalar big.Int `json:"RawScalar"` // For U256 - Proof GProof `json:"Proof"` -} - -type GProof struct { - Data [48]byte `json:"Data"` -} - -func (g *GDataProof) UnmarshalJSON(data []byte) error { - var tupleData [2]json.RawMessage - - if err := json.Unmarshal(data, &tupleData); err != nil { - return err - } - - // Unmarshal RawScalar and remove the '0x' prefix - var rawScalarString string - if err := json.Unmarshal(tupleData[0], &rawScalarString); err != nil { - return err - } - - fmt.Println("RawScalarString:", rawScalarString) - - // Strip '0x' prefix and convert to big.Int - trimmedScalarString := strings.TrimPrefix(rawScalarString, "0x") - rawScalar, ok := new(big.Int).SetString(trimmedScalarString, 16) - if !ok { - fmt.Printf("Failed to convert RawScalar to big.Int, string was: %s\n", trimmedScalarString) - return fmt.Errorf("invalid RawScalar format") - } - g.RawScalar = *rawScalar - - // Unmarshal Proof - var proof [48]byte - if err := json.Unmarshal(tupleData[1], &proof); err != nil { - return err - } - g.Proof = GProof{proof} - - return nil -} - -func formatBigIntWithCommas(b *big.Int) string { - if b == nil { - return "" - } - - numStr := b.String() - - // Starting index for inserting commas - startOffset := 0 - if numStr[0] == '-' { - startOffset = 1 // Keep the negative sign intact - } - - // Slice to hold the parts of the number - var parts []string - - // Iterate over the string in reverse, collecting slices of 3 digits - for i := len(numStr); i > startOffset; i -= 3 { - end := i - start := i - 3 - if start < startOffset { - start = startOffset - } - parts = append([]string{numStr[start:end]}, parts...) - } - - // Join the parts with commas - return strings.Join(parts, ",") -} - -func (g *GDataProof) MarshalJSON() ([]byte, error) { - rawScalarStr := formatBigIntWithCommas(&g.RawScalar) - proofHex := fmt.Sprintf("0x%x", g.Proof.Data) - return json.Marshal([]interface{}{rawScalarStr, proofHex}) -} - -type ProofResponse struct { - DataProof DataProof - Message Message // Interface to capture different message types -} - -type TxDataRoot struct { - DataRoot types.Hash - BlobRoot types.Hash - BridgeRoot types.Hash -} - -// DataProof struct represents the data proof response -type DataProof struct { - Roots TxDataRoot - Proof []types.Hash - NumberOfLeaves uint32 // Change to uint32 to match Rust u32 - LeafIndex uint32 // Change to uint32 to match Rust u32 - Leaf types.Hash -} - -// Message interface represents the enum variants -type Message interface { - isMessage() -} - -type BoundedData struct { - Data []byte -} - -// BoundedDataMaxLen is the maximum length for the bounded data -const BoundedDataMaxLen = 32 // Adjust the maximum length as needed - -// ArbitraryMessage struct represents the ArbitraryMessage variant -type ArbitraryMessage struct { - BoundedData -} - -func (a *ArbitraryMessage) isMessage() {} - -// FungibleToken struct represents the FungibleToken variant -type FungibleToken struct { - AssetID types.Hash - Amount uint128 // Define uint128 type as needed -} - -func (f *FungibleToken) isMessage() {} - -type uint128 uint64 - diff --git a/src/rpc/submit.go b/src/rpc/submit.go deleted file mode 100644 index 5035d48..0000000 --- a/src/rpc/submit.go +++ /dev/null @@ -1,88 +0,0 @@ -package rpc - -import ( - "context" - "fmt" - "sync" - - "github.com/availproject/avail-go-sdk/src/extrinsic" - - "github.com/centrifuge/go-substrate-rpc-client/v4/client" - "github.com/centrifuge/go-substrate-rpc-client/v4/config" - gethrpc "github.com/centrifuge/go-substrate-rpc-client/v4/gethrpc" - "github.com/centrifuge/go-substrate-rpc-client/v4/types" - "github.com/centrifuge/go-substrate-rpc-client/v4/types/codec" -) - -type ExtrinsicStatusSubscription struct { - sub *gethrpc.ClientSubscription - channel chan types.ExtrinsicStatus - quitOnce sync.Once // ensures quit is closed once -} - -// Chan returns the subscription channel. -// -// The channel is closed when Unsubscribe is called on the subscription. -func (s *ExtrinsicStatusSubscription) Chan() <-chan types.ExtrinsicStatus { - return s.channel -} - -// Err returns the subscription error channel. The intended use of Err is to schedule -// resubscription when the client connection is closed unexpectedly. -// -// The error channel receives a value when the subscription has ended due -// to an error. The received error is nil if Close has been called -// on the underlying client and no other error has occurred. -// -// The error channel is closed when Unsubscribe is called on the subscription. -func (s *ExtrinsicStatusSubscription) Err() <-chan error { - return s.sub.Err() -} - -// Unsubscribe unsubscribes the notification and closes the error channel. -// It can safely be called more than once. -func (s *ExtrinsicStatusSubscription) Unsubscribe() { - s.sub.Unsubscribe() - s.quitOnce.Do(func() { - close(s.channel) - }) -} - -// SubmitAndWatchExtrinsic will submit and subscribe to watch an extrinsic until unsubscribed, returning a subscription -// that will receive server notifications containing the extrinsic status updates. -func SubmitAndWatchExtrinsic(xt extrinsic.Extrinsic, client client.Client) (*ExtrinsicStatusSubscription, error) { //nolint:lll - ctx, cancel := context.WithTimeout(context.Background(), config.Default().SubscribeTimeout) - defer cancel() - - c := make(chan types.ExtrinsicStatus) - - enc, err := codec.EncodeToHex(xt) - if err != nil { - return nil, err - } - - sub, err := client.Subscribe(ctx, "author", "submitAndWatchExtrinsic", "unwatchExtrinsic", "extrinsicUpdate", - c, enc) - if err != nil { - return nil, err - } - - return &ExtrinsicStatusSubscription{sub: sub, channel: c}, nil -} - -func SubmitExtrinsic(xt extrinsic.Extrinsic, client client.Client) (types.Hash, error) { - enc, err := codec.EncodeToHex(xt) - - if err != nil { - return types.Hash{}, err - } - fmt.Println(enc) - - var res string - err = client.Call(&res, "author_submitExtrinsic", enc) - if err != nil { - return types.Hash{}, err - } - - return types.NewHashFromHexString(res) -} diff --git a/src/sdk/call/call.go b/src/sdk/call/call.go deleted file mode 100644 index 9b59aef..0000000 --- a/src/sdk/call/call.go +++ /dev/null @@ -1,55 +0,0 @@ -package call - -import ( - "encoding/hex" - "fmt" - - "github.com/availproject/avail-go-sdk/src/rpc" - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/types" -) - -func Query_proof(api *sdk.SubstrateAPI, testCell []rpc.Cell, blockHash types.Hash) ([]rpc.GDataProof, error) { - var result []rpc.GDataProof - err := api.Client.Call(&result, "kate_queryProof", testCell, blockHash) - if err != nil { - return nil, err - } - return result, nil -} - -func Author_Rotate(api *sdk.SubstrateAPI) ([]byte, error) { - var result string - err := api.Client.Call(&result, "author_rotateKeys", nil) - if err != nil { - return nil, err - } - if len(result) > 2 && result[:2] == "0x" { - result = result[2:] - } - - // Decode the hex string - decodedResult, err := hex.DecodeString(result) - if err != nil { - panic(fmt.Errorf("failed to decode result: %w", err)) - } - return decodedResult, nil -} - -func Query_rows(api *sdk.SubstrateAPI, arr []uint32, h types.Hash) ([][]sdk.BigInt, error) { - var response [][]sdk.BigInt - err := api.Client.Call(&response, "kate_queryRows", arr, h) - if err != nil { - return nil, err - } - return response, nil -} - -func Query_dataproof(api *sdk.SubstrateAPI, transactionIndex types.U32, h types.Hash) (rpc.ProofResponse, error) { - var response rpc.ProofResponse - err := api.Client.Call(&response, "kate_queryDataProof", transactionIndex, h) - if err != nil { - return rpc.ProofResponse{}, err - } - return response, nil -} diff --git a/src/sdk/callExtrinsic.go b/src/sdk/callExtrinsic.go deleted file mode 100644 index 292da00..0000000 --- a/src/sdk/callExtrinsic.go +++ /dev/null @@ -1,208 +0,0 @@ -package sdk - -import ( - "encoding/hex" - "fmt" - "log" - "strings" - "time" - - "github.com/availproject/avail-go-sdk/src/extrinsic" - "github.com/availproject/avail-go-sdk/src/rpc" - - "github.com/centrifuge/go-substrate-rpc-client/v4/signature" - "github.com/centrifuge/go-substrate-rpc-client/v4/types" - "github.com/ethereum/go-ethereum/common/hexutil" - "golang.org/x/crypto/blake2b" -) - -func CreateExtrinsic(api *SubstrateAPI, ext_call string, keyring signature.KeyringPair, AppID int, arg ...interface{}) (extrinsic.Extrinsic, error) { - meta, err := api.RPC.State.GetMetadataLatest() - if err != nil { - return extrinsic.Extrinsic{}, err - } - call, err := types.NewCall(meta, ext_call, arg...) - if err != nil { - return extrinsic.Extrinsic{}, err - } - ext := extrinsic.NewExtrinsic(call) - genesisHash, err := api.RPC.Chain.GetBlockHash(0) - if err != nil { - return extrinsic.Extrinsic{}, err - } - rv, err := api.RPC.State.GetRuntimeVersionLatest() - if err != nil { - return extrinsic.Extrinsic{}, err - } - key, err := types.CreateStorageKey(meta, "System", "Account", keyring.PublicKey) - if err != nil { - return extrinsic.Extrinsic{}, err - } - - var accountInfo types.AccountInfo - ok, err := api.RPC.State.GetStorageLatest(key, &accountInfo) - if err != nil || !ok { - return extrinsic.Extrinsic{}, err - } - nonce := uint32(accountInfo.Nonce) - options := extrinsic.SignatureOptions{ - BlockHash: genesisHash, - Era: extrinsic.ExtrinsicEra{IsMortalEra: false}, - GenesisHash: genesisHash, - Nonce: types.NewUCompactFromUInt(uint64(nonce)), - SpecVersion: rv.SpecVersion, - Tip: types.NewUCompactFromUInt(100), - AppID: types.NewUCompactFromUInt(uint64(AppID)), - TransactionVersion: rv.TransactionVersion, - } - - err = ext.Sign(keyring, options) - if err != nil { - panic(fmt.Sprintf("cannot sign:%v", err)) - } - return ext, nil -} - -func NewExtrinsic(api *SubstrateAPI, ext_call string, keyring signature.KeyringPair, AppID int, arg ...interface{}) (types.Hash, error) { - meta, err := api.RPC.State.GetMetadataLatest() - if err != nil { - return types.Hash{}, err - } - call, err := types.NewCall(meta, ext_call, arg...) - if err != nil { - return types.Hash{}, err - } - ext := extrinsic.NewExtrinsic(call) - genesisHash, err := api.RPC.Chain.GetBlockHash(0) - if err != nil { - return types.Hash{}, err - } - rv, err := api.RPC.State.GetRuntimeVersionLatest() - if err != nil { - return types.Hash{}, err - } - key, err := types.CreateStorageKey(meta, "System", "Account", keyring.PublicKey) - if err != nil { - return types.Hash{}, err - } - - var accountInfo types.AccountInfo - ok, err := api.RPC.State.GetStorageLatest(key, &accountInfo) - if err != nil || !ok { - return types.Hash{}, err - } - nonce := uint32(accountInfo.Nonce) - options := extrinsic.SignatureOptions{ - BlockHash: genesisHash, - Era: extrinsic.ExtrinsicEra{IsMortalEra: false}, - GenesisHash: genesisHash, - Nonce: types.NewUCompactFromUInt(uint64(nonce)), - SpecVersion: rv.SpecVersion, - Tip: types.NewUCompactFromUInt(100), - AppID: types.NewUCompactFromUInt(uint64(AppID)), - TransactionVersion: rv.TransactionVersion, - } - err = ext.Sign(keyring, options) - if err != nil { - panic(fmt.Sprintf("cannot sign:%v", err)) - } - hash, err := rpc.SubmitExtrinsic(ext, api.Client) - if err != nil { - panic(fmt.Sprintf("cannot submit extrinsic:%v", err)) - } - - fmt.Printf("Data submitted using APPID: %v \n", AppID) - return hash, nil -} - -func NewExtrinsicWatch(api *SubstrateAPI, ext_call string, keyring signature.KeyringPair, final chan types.Hash, txHash chan types.Hash, AppID int, WaitForInclusion WaitFor, arg ...interface{}) error { - meta, err := api.RPC.State.GetMetadataLatest() - if err != nil { - return err - } - call, err := types.NewCall(meta, ext_call, arg...) - if err != nil { - return err - } - ext := extrinsic.NewExtrinsic(call) - genesisHash, err := api.RPC.Chain.GetBlockHash(0) - if err != nil { - return err - } - rv, err := api.RPC.State.GetRuntimeVersionLatest() - if err != nil { - return err - } - key, err := types.CreateStorageKey(meta, "System", "Account", keyring.PublicKey) - if err != nil { - return err - } - - var accountInfo types.AccountInfo - ok, err := api.RPC.State.GetStorageLatest(key, &accountInfo) - if err != nil || !ok { - return err - } - nonce := uint32(accountInfo.Nonce) - options := extrinsic.SignatureOptions{ - BlockHash: genesisHash, - Era: extrinsic.ExtrinsicEra{IsMortalEra: false}, - GenesisHash: genesisHash, - Nonce: types.NewUCompactFromUInt(uint64(nonce)), - SpecVersion: rv.SpecVersion, - Tip: types.NewUCompactFromUInt(100), - AppID: types.NewUCompactFromUInt(uint64(AppID)), - TransactionVersion: rv.TransactionVersion, - } - err = ext.Sign(keyring, options) - if err != nil { - panic(fmt.Sprintf("cannot sign:%v", err)) - } - - go func() { - enc, _ := EncodeToHex(ext) - - cleanedHexString := strings.TrimPrefix(enc, "0x") - bytes, err := hex.DecodeString(cleanedHexString) - if err != nil { - log.Fatal(err) - } - hash := blake2b.Sum256(bytes) - ext_z := hexutil.Encode(hash[:]) - hash, err = NewHashFromHexString(ext_z) - if err != nil { - log.Fatal(err) - } - txHash <- hash - }() - - sub, err := rpc.SubmitAndWatchExtrinsic(ext, api.Client) - if err != nil { - panic(fmt.Sprintf("cannot submit extrinsic:%v", err)) - } - - fmt.Printf("Transaction being submitted .... ⏳Waiting for block inclusion..") - - defer sub.Unsubscribe() - timeout := time.After(200 * time.Second) - for { - select { - case status := <-sub.Chan(): - switch WaitForInclusion { - case BlockInclusion: - if status.IsInBlock { - final <- status.AsInBlock - return err - } - case BlockFinalization: - if status.IsFinalized { - final <- status.AsFinalized - return err - } - } - case <-timeout: - fmt.Printf("timeout of 200 seconds reached without getting finalized status for extrinsic") - return err - } - } -} diff --git a/src/sdk/events.go b/src/sdk/events.go deleted file mode 100644 index a95d946..0000000 --- a/src/sdk/events.go +++ /dev/null @@ -1,525 +0,0 @@ -package sdk - -import ( - "encoding/hex" - "fmt" - - "log" - "math/big" - - "github.com/centrifuge/go-substrate-rpc-client/v4/registry" - "github.com/centrifuge/go-substrate-rpc-client/v4/registry/parser" - retriever "github.com/centrifuge/go-substrate-rpc-client/v4/registry/retriever" - "github.com/centrifuge/go-substrate-rpc-client/v4/registry/state" - "github.com/centrifuge/go-substrate-rpc-client/v4/types" - "github.com/vedhavyas/go-subkey" -) - -func EventParser(api *SubstrateAPI, h types.Hash, eventParse string) { - retriever, err := retriever.NewDefaultEventRetriever(state.NewEventProvider(api.RPC.State), api.RPC.State) - if err != nil { - log.Printf("Couldn't create event retriever") - } - - events, err := retriever.GetEvents(h) - - if err != nil { - log.Printf("Couldn't retrieve events") - } - - switch eventParse { - case "DataSubmitted": - ParseDataSubmitted(events) - case "ApplicationKeyCreated": - parseApplicationKeyCreated(events) - case "ApplicationKeySet": - parseApplicationKeySet(events) - case "BalanceTransfer": - parseBalanceTransfer(events) - case "Bond": - parseBond(events) - } -} -func ParseDataSubmitted(events []*parser.Event) { - for _, event := range events { - if event.Name == "DataAvailability.DataSubmitted" { - from, _ := registry.ProcessDecodedFieldValue[*types.AccountID]( - event.Fields, - func(fieldIndex int, field *registry.DecodedField) bool { - - return field.Name == "sp_core.crypto.AccountId32.who" - }, - func(value any) (*types.AccountID, error) { - fields, ok := value.(registry.DecodedFields) - - if !ok { - return nil, fmt.Errorf("unexpected value: %v", value) - } - - accByteSlice, err := registry.GetDecodedFieldAsSliceOfType[types.U8](fields, func(fieldIndex int, field *registry.DecodedField) bool { - return fieldIndex == 0 - }) - - if err != nil { - return nil, err - } - - var accBytes []byte - - for _, accByte := range accByteSlice { - accBytes = append(accBytes, byte(accByte)) - } - - return types.NewAccountID(accBytes) - }, - ) - // a := from.ToHexString() - - // // add, _ := types.NewAddressFromHexAccountID(a) - // fmt.Println(from) - // fmt.Printf("from address read from event: %s \n", a) - has := subkey.SS58Encode(from.ToBytes(), 42) - fmt.Printf("from address read from event: %s \n", has) - dataHash, err := registry.ProcessDecodedFieldValue[*types.Hash]( - event.Fields, - func(fieldIndex int, field *registry.DecodedField) bool { - return fieldIndex == 1 - }, - func(value any) (*types.Hash, error) { - fields, ok := value.(registry.DecodedFields) - if !ok { - return nil, fmt.Errorf("unexpected value: %v", value) - } - - hashByteSlice, err := registry.GetDecodedFieldAsSliceOfType[types.U8](fields, func(fieldIndex int, field *registry.DecodedField) bool { - return fieldIndex == 0 - }) - - if err != nil { - return nil, err - } - - var hashBytes []byte - for _, hashByte := range hashByteSlice { - hashBytes = append(hashBytes, byte(hashByte)) - } - - hash := types.NewHash(hashBytes) - return &hash, nil - }, - ) - if err != nil { - fmt.Printf("DataHash parsing err: %s\n", err.Error()) - } else if dataHash == nil { - fmt.Println("DataHash is nil") - } else { - fmt.Printf("DataHash read from event: %s \n", dataHash.Hex()) - } - - } - parseTransactionFee(event) - } -} - -func parseTransactionFee(event *parser.Event) { - if event.Name == "TransactionPayment.TransactionFeePaid" { - - amount, err := registry.GetDecodedFieldAsType[types.U128]( - event.Fields, - func(fieldIndex int, field *registry.DecodedField) bool { - return fieldIndex == 1 - }, - ) - if err != nil { - fmt.Printf("Amount parsing err: %s\n", err.Error()) - } - fmt.Printf("Actual Fee from TransactionPayment.TransactionFeePaid event: %s \n", convInt(amount.String())) - if err != nil { - fmt.Printf("Balances.Deposit.Who: %s\n", err.Error()) - } - } - -} - -func parseApplicationKeyCreated(events []*parser.Event) { - for _, event := range events { - if event.Name == "DataAvailability.ApplicationKeyCreated" { - owner, _ := registry.ProcessDecodedFieldValue[*types.AccountID]( - event.Fields, - func(fieldIndex int, field *registry.DecodedField) bool { - - return field.Name == "sp_core.crypto.AccountId32.owner" - }, - func(value any) (*types.AccountID, error) { - fields, ok := value.(registry.DecodedFields) - - if !ok { - return nil, fmt.Errorf("unexpected value: %v", value) - } - - accByteSlice, err := registry.GetDecodedFieldAsSliceOfType[types.U8](fields, func(fieldIndex int, field *registry.DecodedField) bool { - return fieldIndex == 0 - }) - - if err != nil { - return nil, err - } - - var accBytes []byte - - for _, accByte := range accByteSlice { - accBytes = append(accBytes, byte(accByte)) - } - - return types.NewAccountID(accBytes) - }, - ) - // a := from.ToHexString() - - // // add, _ := types.NewAddressFromHexAccountID(a) - // fmt.Println(from) - // fmt.Printf("from address read from event: %s \n", a) - has := subkey.SS58Encode(owner.ToBytes(), 42) - fmt.Printf("from address read from event: %s \n", has) - - id, err := registry.ProcessDecodedFieldValue[types.UCompact]( - event.Fields, - func(fieldIndex int, field *registry.DecodedField) bool { - return fieldIndex == 2 - }, - func(value any) (types.UCompact, error) { - fields, ok := value.(registry.DecodedFields) - if !ok { - return types.NewUCompact(big.NewInt(0)), fmt.Errorf("unexpected value type: %T", value) - } - - // Assuming the UCompact value is the first (and only) field in this struct - ucompact, err := registry.GetDecodedFieldAsType[types.UCompact](fields, func(fieldIndex int, field *registry.DecodedField) bool { - return fieldIndex == 0 - }) - - if err != nil { - return types.NewUCompact(big.NewInt(0)), fmt.Errorf("error getting UCompact field: %w", err) - } - - return ucompact, nil - }, - ) - if err != nil { - fmt.Printf("AppId parsing err: %s\n", err.Error()) - } else { - fmt.Println(id.Int64()) - } - - appKey, err := registry.ProcessDecodedFieldValue[types.Bytes]( - event.Fields, - func(fieldIndex int, field *registry.DecodedField) bool { - return fieldIndex == 0 // Adjust this index if needed - }, - func(value any) (types.Bytes, error) { - fields, ok := value.(registry.DecodedFields) - if !ok { - return nil, fmt.Errorf("unexpected value type: %T", value) - } - - // The BoundedVec is likely represented as a slice of U8 - byteSlice, err := registry.GetDecodedFieldAsSliceOfType[types.U8](fields, func(fieldIndex int, field *registry.DecodedField) bool { - return fieldIndex == 0 - }) - - if err != nil { - return nil, fmt.Errorf("error getting byte slice: %w", err) - } - - // Convert the slice of U8 to types.Bytes - bytes := make(types.Bytes, len(byteSlice)) - for i, b := range byteSlice { - bytes[i] = byte(b) - } - - return bytes, nil - }, - ) - - if err != nil { - fmt.Printf("AppKey parsing err: %s\n", err.Error()) - } else { - // Convert Bytes to string for printing - stringValue := string(appKey) - fmt.Printf("AppKey from event (as string): %s\n", stringValue) - - // If you also want to see the hex representation: - hexString := hex.EncodeToString(appKey) - fmt.Printf("AppKey from event (as hex): 0x%s\n", hexString) - } - - } - parseTransactionFee(event) - } -} - -func parseApplicationKeySet(events []*parser.Event) { - for _, event := range events { - if event.Name == "DataAvailability.ApplicationKeySet" { - owner, _ := registry.ProcessDecodedFieldValue[*types.AccountID]( - event.Fields, - func(fieldIndex int, field *registry.DecodedField) bool { - - return field.Name == "sp_core.crypto.AccountId32.owner" - }, - func(value any) (*types.AccountID, error) { - fields, ok := value.(registry.DecodedFields) - - if !ok { - return nil, fmt.Errorf("unexpected value: %v", value) - } - - accByteSlice, err := registry.GetDecodedFieldAsSliceOfType[types.U8](fields, func(fieldIndex int, field *registry.DecodedField) bool { - return fieldIndex == 0 - }) - - if err != nil { - return nil, err - } - - var accBytes []byte - - for _, accByte := range accByteSlice { - accBytes = append(accBytes, byte(accByte)) - } - - return types.NewAccountID(accBytes) - }, - ) - // a := from.ToHexString() - - // // add, _ := types.NewAddressFromHexAccountID(a) - // fmt.Println(from) - // fmt.Printf("from address read from event: %s \n", a) - has := subkey.SS58Encode(owner.ToBytes(), 42) - fmt.Printf("from address read from event: %s \n", has) - - id, err := registry.ProcessDecodedFieldValue[types.UCompact]( - event.Fields, - func(fieldIndex int, field *registry.DecodedField) bool { - return fieldIndex == 2 - }, - func(value any) (types.UCompact, error) { - fields, ok := value.(registry.DecodedFields) - if !ok { - return types.NewUCompact(big.NewInt(0)), fmt.Errorf("unexpected value type: %T", value) - } - - // Assuming the UCompact value is the first (and only) field in this struct - ucompact, err := registry.GetDecodedFieldAsType[types.UCompact](fields, func(fieldIndex int, field *registry.DecodedField) bool { - return fieldIndex == 0 - }) - - if err != nil { - return types.NewUCompact(big.NewInt(0)), fmt.Errorf("error getting UCompact field: %w", err) - } - - return ucompact, nil - }, - ) - if err != nil { - fmt.Printf("AppId parsing err: %s\n", err.Error()) - } else { - fmt.Println(id.Int64()) - } - - appKey, err := registry.ProcessDecodedFieldValue[types.Bytes]( - event.Fields, - func(fieldIndex int, field *registry.DecodedField) bool { - return fieldIndex == 0 // Adjust this index if needed - }, - func(value any) (types.Bytes, error) { - fields, ok := value.(registry.DecodedFields) - if !ok { - return nil, fmt.Errorf("unexpected value type: %T", value) - } - - // The BoundedVec is likely represented as a slice of U8 - byteSlice, err := registry.GetDecodedFieldAsSliceOfType[types.U8](fields, func(fieldIndex int, field *registry.DecodedField) bool { - return fieldIndex == 0 - }) - - if err != nil { - return nil, fmt.Errorf("error getting byte slice: %w", err) - } - - // Convert the slice of U8 to types.Bytes - bytes := make(types.Bytes, len(byteSlice)) - for i, b := range byteSlice { - bytes[i] = byte(b) - } - - return bytes, nil - }, - ) - - if err != nil { - fmt.Printf("AppKey parsing err: %s\n", err.Error()) - } else { - // Convert Bytes to string for printing - stringValue := string(appKey) - fmt.Printf("AppKey from event (as string): %s\n", stringValue) - - // If you also want to see the hex representation: - hexString := hex.EncodeToString(appKey) - fmt.Printf("AppKey from event (as hex): 0x%s\n", hexString) - } - - } - parseTransactionFee(event) - } -} - -func parseBalanceTransfer(events []*parser.Event) { - for _, event := range events { - if event.Name == "Balances.Transfer" { - from, err := registry.ProcessDecodedFieldValue[*types.AccountID]( - event.Fields, - func(fieldIndex int, field *registry.DecodedField) bool { - - return field.Name == "sp_core.crypto.AccountId32.from" - }, - func(value any) (*types.AccountID, error) { - fields, ok := value.(registry.DecodedFields) - - if !ok { - return nil, fmt.Errorf("unexpected value: %v", value) - } - - accByteSlice, err := registry.GetDecodedFieldAsSliceOfType[types.U8](fields, func(fieldIndex int, field *registry.DecodedField) bool { - return fieldIndex == 0 - }) - - if err != nil { - return nil, err - } - - var accBytes []byte - - for _, accByte := range accByteSlice { - accBytes = append(accBytes, byte(accByte)) - } - - return types.NewAccountID(accBytes) - }, - ) - a := from.ToHexString() - - // // add, _ := types.NewAddressFromHexAccountID(a) - // fmt.Println(from) - fmt.Printf("from address read from event: %s \n", a) - - to, err := registry.ProcessDecodedFieldValue[*types.AccountID]( - event.Fields, - - func(fieldIndex int, field *registry.DecodedField) bool { - - return field.Name == "sp_core.crypto.AccountId32.to" - }, - func(value any) (*types.AccountID, error) { - fields, ok := value.(registry.DecodedFields) - - if !ok { - return nil, fmt.Errorf("unexpected value: %v", value) - } - - accByteSlice, err := registry.GetDecodedFieldAsSliceOfType[types.U8](fields, func(fieldIndex int, field *registry.DecodedField) bool { - return fieldIndex == 0 - }) - - if err != nil { - return nil, err - } - - var accBytes []byte - - for _, accByte := range accByteSlice { - accBytes = append(accBytes, byte(accByte)) - } - - return types.NewAccountID(accBytes) - }, - ) - if err != nil { - fmt.Printf("TO parsing err: %s\n", err.Error()) - } - fmt.Printf("To address read from event: %s \n", to.ToHexString()) - amount, err := registry.GetDecodedFieldAsType[types.U128]( - event.Fields, - func(fieldIndex int, field *registry.DecodedField) bool { - return fieldIndex == 2 - }, - ) - if err != nil { - fmt.Printf("Amount parsing err: %s\n", err.Error()) - } - fmt.Printf("Amount transferred : %s \n", convInt(amount.String())) - if err != nil { - fmt.Printf("Balances.Deposit.Who: %s\n", err.Error()) - } - } - parseTransactionFee(event) - } -} - -func parseBond(events []*parser.Event) { - for _, event := range events { - if event.Name == "Staking.Bonded" { - from, err := registry.ProcessDecodedFieldValue[*types.AccountID]( - event.Fields, - func(fieldIndex int, field *registry.DecodedField) bool { - - return field.Name == "sp_core.crypto.AccountId32.stash" - }, - func(value any) (*types.AccountID, error) { - fields, ok := value.(registry.DecodedFields) - - if !ok { - return nil, fmt.Errorf("unexpected value: %v", value) - } - - accByteSlice, err := registry.GetDecodedFieldAsSliceOfType[types.U8](fields, func(fieldIndex int, field *registry.DecodedField) bool { - return fieldIndex == 0 - }) - - if err != nil { - return nil, err - } - - var accBytes []byte - - for _, accByte := range accByteSlice { - accBytes = append(accBytes, byte(accByte)) - } - - return types.NewAccountID(accBytes) - }, - ) - a := from.ToHexString() - - // // add, _ := types.NewAddressFromHexAccountID(a) - // fmt.Println(from) - fmt.Printf("stash address read from event: %s \n", a) - - amount, err := registry.GetDecodedFieldAsType[types.U128]( - event.Fields, - func(fieldIndex int, field *registry.DecodedField) bool { - return fieldIndex == 1 - }, - ) - if err != nil { - fmt.Printf("Amount parsing err: %s\n", err.Error()) - } - fmt.Printf("Amount staked : %s \n", convInt(amount.String())) - if err != nil { - fmt.Printf("Amount staked: %s\n", err.Error()) - } - } - parseTransactionFee(event) - } -} diff --git a/src/sdk/helper.go b/src/sdk/helper.go deleted file mode 100644 index 59ed8d5..0000000 --- a/src/sdk/helper.go +++ /dev/null @@ -1,359 +0,0 @@ -package sdk - -import ( - "crypto/rand" - "encoding/hex" - "encoding/json" - "fmt" - "log" - "math/big" - "strings" - - "github.com/availproject/avail-go-sdk/src/rpc" - - "github.com/centrifuge/go-substrate-rpc-client/v4/scale" - "github.com/centrifuge/go-substrate-rpc-client/v4/signature" - "github.com/centrifuge/go-substrate-rpc-client/v4/types" - "github.com/centrifuge/go-substrate-rpc-client/v4/types/codec" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/vedhavyas/go-subkey" - "golang.org/x/crypto/blake2b" -) - -func ConvertMultiAddress(receiver string) (types.MultiAddress, error) { - _, pubkeyBytes, _ := subkey.SS58Decode(receiver) - address := subkey.EncodeHex(pubkeyBytes) - - dest, err := types.NewMultiAddressFromHexAccountID(address) - if err != nil { - _ = fmt.Errorf("cannot create address from given hex:%w", err) - return types.MultiAddress{}, err - } - return dest, nil -} - -type BigInt struct { - *big.Int -} - -func ConvertToBondAmount(input int64) *big.Int { - // Create a new big.Int for the input - inputBig := big.NewInt(input) - - // Create a big.Int for 10^18 - multiplier := new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil) - - // Multiply input by 10^18 - result := new(big.Int).Mul(inputBig, multiplier) - - return result -} - -// UnmarshalJSON defines custom unmarshalling for BigInt. -func (bi *BigInt) UnmarshalJSON(data []byte) error { - // Unmarshal as raw JSON string - var rawString string - if err := json.Unmarshal(data, &rawString); err != nil { - return err - } - - // Remove 0x prefix if present - str := strings.TrimPrefix(rawString, "0x") - - // Initialize bi.Int if it's nil - if bi.Int == nil { - bi.Int = new(big.Int) - } - - // If the string is empty, set bi to zero - if str == "" { - bi.SetInt64(0) - return nil - } - - // Parse the string in base 16 - _, success := bi.SetString(str, 16) - if !success { - return fmt.Errorf("invalid hex string") - } - - return nil -} - -func FormatBN(n BigInt) string { - s := n.String() // Convert number to string - var result strings.Builder - count := 0 - - for i := len(s) - 1; i >= 0; i-- { - if count == 3 { - result.WriteString(",") - count = 0 - } - result.WriteByte(s[i]) - count++ - } - - // Reverse the string to get the correct order - reversed := result.String() - var formatted strings.Builder - for i := len(reversed) - 1; i >= 0; i-- { - formatted.WriteByte(reversed[i]) - } - - return formatted.String() -} -func RandToken(n int) (string, error) { - bytes := make([]byte, n) - if _, err := rand.Read(bytes); err != nil { - return "", err - } - return hex.EncodeToString(bytes), nil -} - -func KeyringFromSeed(seed string) (signature.KeyringPair, error) { - return signature.KeyringPairFromSecret(seed, 42) -} - -type Bytes []byte - -func NewBytes(b []byte) Bytes { - return Bytes(b) -} - -func EncodeToHex(hash interface{}) (string, error) { - return codec.EncodeToHex(hash) -} - -func convInt(val string) string { - bigIntValue := new(big.Int) - bigIntValue.SetString(val, 10) - - divisor := new(big.Int) - divisor.SetString("1000000000000000000", 10) - - bigFloatValue := new(big.Float).SetInt(bigIntValue) - divisorFloat := new(big.Float).SetInt(divisor) - result := new(big.Float).Quo(bigFloatValue, divisorFloat) - - x := (result.Text('f', 18)) - return x -} - -func CreateChannel() chan types.Hash { - c := make(chan types.Hash, 1) - return c -} - -func ExistentialDeposit(api *SubstrateAPI) { - - meta, err := api.RPC.State.GetMetadataLatest() - if err != nil { - panic(fmt.Sprintf("cannot get metadata: %v", err)) - } - var existentialDeposit types.U128 - - for _, mod := range meta.AsMetadataV14.Pallets { - if string(mod.Name) == "Balances" { - for _, constant := range mod.Constants { - if string(constant.Name) == "ExistentialDeposit" { - err = codec.Decode(constant.Value, &existentialDeposit) - if err != nil { - log.Fatalf("Failed to decode ExistentialDeposit: %v", err) - } - fmt.Printf("Existential Deposit: %d\n", existentialDeposit) - return - } - } - } - } - - fmt.Printf("Existential Deposit: %d\n", existentialDeposit) -} - -func NewCall(api *SubstrateAPI, callName string, args ...interface{}) (types.Call, error) { - meta, err := api.RPC.State.GetMetadataLatest() - if err != nil { - return types.Call{}, err - } - return types.NewCall(meta, callName, args...) -} - -func NewHashFromHexString(hexStr string) (types.Hash, error) { - return types.NewHashFromHexString(hexStr) -} - -func NewU256(value *big.Int) types.U256 { - return types.NewU256(*value) -} - -func NewMultiAddressFromHexAccountID(hexStr string) (types.MultiAddress, error) { - return types.NewMultiAddressFromHexAccountID(hexStr) -} - -func NewMultiAddressFromAccountID(accountID []byte) (types.MultiAddress, error) { - return types.NewMultiAddressFromAccountID(accountID) -} - -func NewU8(value uint8) types.U8 { - return types.U8(value) -} - -func NewU32(value uint32) types.U32 { - return types.U32(value) -} - -func NewU64(value uint64) types.U64 { - return types.U64(value) -} - -func NewU128(value *big.Int) types.U128 { - return types.NewU128(*value) -} - -func KeyringPairFromSecret(seed string, keyType uint16) (signature.KeyringPair, error) { - return signature.KeyringPairFromSecret(seed, keyType) -} - -type WaitFor int - -const ( - BlockInclusion WaitFor = iota + 1 - BlockFinalization -) - -func (w WaitFor) String() string { - return [...]string{"BlockInclusion", "BlockFinalization"}[w-1] -} - -// EnumIndex - Creating common behavior - give the type a EnumIndex function -func (w WaitFor) EnumIndex() int { - return int(w) -} - -type Payee uint8 - -const ( - Staked WaitFor = iota - Stash - Controller - Account - None -) - -func (w Payee) String() string { - return [...]string{"Staked", "Stash", "Controller", "Account", "None"}[w] -} - -// EnumIndex - Creating common behavior - give the type a EnumIndex function -func (w Payee) EnumIndex() uint8 { - return uint8(w) -} - -func GetData(hash types.Hash, api *SubstrateAPI, txHash types.Hash) error { - block, err := rpc.GetAvailBlock(hash, api.Client) - if err != nil { - return fmt.Errorf("cannot get block by hash:%w", err) - } - for _, ext := range block.Block.Extrinsics { - - // these values below are specific indexes only for data submission, differs with each extrinsic - if ext.IsSigned() && ext.Method.CallIndex.SectionIndex == 29 && ext.Method.CallIndex.MethodIndex == 1 { - enc, _ := EncodeToHex(ext) - cleanedHexString := strings.TrimPrefix(enc, "0x") - bytes, err := hex.DecodeString(cleanedHexString) - if err != nil { - log.Fatal(err) - } - hash := blake2b.Sum256(bytes) - txHashDecoded := hexutil.Encode(hash[:]) - if txHashDecoded == txHash.Hex() { - arg := ext.Method.Args - str := string(arg) - slice := str[1:] - - fmt.Println("Data retrieved:", slice) - } - } - } - return nil -} - -type DispatchFeeModifier struct { - WeightMaximumFee types.U128 - WeightFeeDivider types.U32 - WeightFeeMultiplier types.U32 -} - -// Encode implements scale.Encodeable -func (d DispatchFeeModifier) Encode(encoder scale.Encoder) error { - // Encode WeightMaximumFee - if err := encoder.PushByte(1); err != nil { // 1 for Some - return err - } - if err := encoder.Encode(d.WeightMaximumFee); err != nil { - return err - } - - // Encode WeightFeeDivider - if err := encoder.PushByte(1); err != nil { // 1 for Some - return err - } - if err := encoder.Encode(d.WeightFeeDivider); err != nil { - return err - } - - // Encode WeightFeeMultiplier - if err := encoder.PushByte(1); err != nil { // 1 for Some - return err - } - if err := encoder.Encode(d.WeightFeeMultiplier); err != nil { - return err - } - - return nil -} - -// Decode implements scale.Decodeable -func (d *DispatchFeeModifier) Decode(decoder scale.Decoder) error { - // Decode WeightMaximumFee - optionByte, err := decoder.ReadOneByte() - if err != nil { - return err - } - if optionByte == 1 { // Some - if err := decoder.Decode(&d.WeightMaximumFee); err != nil { - return err - } - } else if optionByte != 0 { // Not None (0) or Some (1) - return fmt.Errorf("invalid option byte for WeightMaximumFee: %d", optionByte) - } - - // Decode WeightFeeDivider - optionByte, err = decoder.ReadOneByte() - if err != nil { - return err - } - if optionByte == 1 { // Some - if err := decoder.Decode(&d.WeightFeeDivider); err != nil { - return err - } - } else if optionByte != 0 { // Not None (0) or Some (1) - return fmt.Errorf("invalid option byte for WeightFeeDivider: %d", optionByte) - } - - // Decode WeightFeeMultiplier - optionByte, err = decoder.ReadOneByte() - if err != nil { - return err - } - if optionByte == 1 { // Some - if err := decoder.Decode(&d.WeightFeeMultiplier); err != nil { - return err - } - } else if optionByte != 0 { // Not None (0) or Some (1) - return fmt.Errorf("invalid option byte for WeightFeeMultiplier: %d", optionByte) - } - - return nil -} diff --git a/src/sdk/sdk.go b/src/sdk/sdk.go deleted file mode 100644 index 1652730..0000000 --- a/src/sdk/sdk.go +++ /dev/null @@ -1,32 +0,0 @@ -package sdk - -import ( - "github.com/centrifuge/go-substrate-rpc-client/v4/client" - "github.com/centrifuge/go-substrate-rpc-client/v4/rpc" -) - -type SubstrateAPI struct { - RPC *rpc.RPC - Client client.Client -} - -func NewSDK(url string) (*SubstrateAPI, error) { - cl, err := client.Connect(url) - if err != nil { - return nil, err - } - - newRPC, err := rpc.NewRPC(cl) - if err != nil { - return nil, err - } - - return &SubstrateAPI{ - RPC: newRPC, - Client: cl, - }, nil -} - -func (api *SubstrateAPI) Close() { - api.Client.Close() -} diff --git a/src/sdk/tx/transactions.go b/src/sdk/tx/transactions.go deleted file mode 100644 index 78ab0d7..0000000 --- a/src/sdk/tx/transactions.go +++ /dev/null @@ -1,470 +0,0 @@ -package tx - -import ( - "errors" - "fmt" - "math/big" - "strconv" - - "github.com/availproject/avail-go-sdk/src/sdk" - "github.com/availproject/avail-go-sdk/src/sdk/types" - - "github.com/vedhavyas/go-subkey/v2" -) - -type WaitFor int - -const ( - BlockInclusion WaitFor = iota + 1 - BlockFinalization -) - -func (w WaitFor) String() string { - return [...]string{"BlockInclusion", "BlockFinalization"}[w-1] -} - -// EnumIndex - Creating common behavior - give the type a EnumIndex function -func (w WaitFor) EnumIndex() int { - return int(w) -} - -// SubmitData submits data to the chain -func SubmitData(api *sdk.SubstrateAPI, seed string, AppID int, data string, WaitForInclusion sdk.WaitFor) (types.Hash, types.Hash, error) { - keyringPair, err := sdk.KeyringFromSeed(seed) - if err != nil { - panic(fmt.Sprintf("cannot create KeyPair:%v", err)) - } - BlockHashCh2 := make(chan types.Hash) - txHashCh2 := make(chan types.Hash) - go func() { - err := sdk.NewExtrinsicWatch(api, "DataAvailability.submit_data", keyringPair, BlockHashCh2, txHashCh2, AppID, WaitForInclusion, sdk.NewBytes([]byte(data))) - if err != nil { - fmt.Printf("cannot create extrinsic: %v", err) - close(BlockHashCh2) - close(txHashCh2) - return - } - }() - blockHash := <-BlockHashCh2 - txHash := <-txHashCh2 - return blockHash, txHash, nil -} - -func CreateApplicationKey(api *sdk.SubstrateAPI, seed string, data string, WaitForInclusion sdk.WaitFor) (types.Hash, types.Hash, error) { - keyringPair, err := sdk.KeyringFromSeed(seed) - if err != nil { - panic(fmt.Sprintf("cannot create KeyPair:%v", err)) - } - BlockHashCh2 := make(chan types.Hash) - txHashCh2 := make(chan types.Hash) - go func() { - err := sdk.NewExtrinsicWatch(api, "DataAvailability.create_application_key", keyringPair, BlockHashCh2, txHashCh2, 0, WaitForInclusion, sdk.NewBytes([]byte("22222"))) - if err != nil { - fmt.Printf("cannot create extrinsic: %v", err) - close(BlockHashCh2) - close(txHashCh2) - return - } - - }() - blockHash := <-BlockHashCh2 - txHash := <-txHashCh2 - return blockHash, txHash, nil - -} - -func SetApplicationKey(api *sdk.SubstrateAPI, seed string, WaitForInclusion sdk.WaitFor, oldKey string, newKey string) (types.Hash, types.Hash, error) { - keyringPair, err := sdk.KeyringFromSeed(seed) - if err != nil { - panic(fmt.Sprintf("cannot create KeyPair:%v", err)) - } - BlockHashCh2 := make(chan types.Hash) - txHashCh2 := make(chan types.Hash) - go func() { - call, err := sdk.NewCall(api, "DataAvailability.set_application_key", sdk.NewBytes([]byte(oldKey)), sdk.NewBytes([]byte(newKey))) - if err != nil { - fmt.Printf("cannot create extrinsic: %v", err) - } - err = sdk.NewExtrinsicWatch(api, "Sudo.sudo", keyringPair, BlockHashCh2, txHashCh2, 0, WaitForInclusion, call) - if err != nil { - fmt.Printf("cannot create extrinsic: %v", err) - close(BlockHashCh2) - close(txHashCh2) - return - } - fmt.Println("Transaction submitted successfully") - }() - blockHash := <-BlockHashCh2 - txHash := <-txHashCh2 - return blockHash, txHash, nil - -} - -func SetSubmitDataFeeModifier(api *sdk.SubstrateAPI, seed string, WaitForInclusion sdk.WaitFor, modifier sdk.DispatchFeeModifier) (types.Hash, types.Hash, error) { - keyringPair, err := sdk.KeyringFromSeed(seed) - if err != nil { - panic(fmt.Sprintf("cannot create KeyPair:%v", err)) - } - BlockHashCh2 := make(chan types.Hash) - txHashCh2 := make(chan types.Hash) - - go func() { - call, err := sdk.NewCall(api, "DataAvailability.set_submit_data_fee_modifier", modifier) - if err != nil { - fmt.Printf("cannot create extrinsic: %v", err) - } - err = sdk.NewExtrinsicWatch(api, "Sudo.sudo", keyringPair, BlockHashCh2, txHashCh2, 0, WaitForInclusion, call) - if err != nil { - fmt.Printf("cannot create extrinsic: %v", err) - close(BlockHashCh2) - close(txHashCh2) - return - } - fmt.Println("Transaction submitted successfully") - }() - blockHash := <-BlockHashCh2 - txHash := <-txHashCh2 - return blockHash, txHash, nil - -} - -func SubmitBlockLength(api *sdk.SubstrateAPI, seed string, WaitForInclusion sdk.WaitFor, rows uint32, cols uint32) (types.Hash, types.Hash, error) { - keyringPair, err := sdk.KeyringFromSeed(seed) - if err != nil { - panic(fmt.Sprintf("cannot create KeyPair:%v", err)) - } - BlockHashCh2 := make(chan types.Hash) - txHashCh2 := make(chan types.Hash) - - go func() { - call, err := sdk.NewCall(api, "DataAvailability.submit_block_length_proposal", sdk.NewU32(rows), sdk.NewU32(cols)) - if err != nil { - fmt.Printf("cannot create extrinsic: %v", err) - } - err = sdk.NewExtrinsicWatch(api, "Sudo.sudo", keyringPair, BlockHashCh2, txHashCh2, 0, WaitForInclusion, call) - if err != nil { - fmt.Printf("cannot create extrinsic: %v", err) - close(BlockHashCh2) - close(txHashCh2) - return - } - - }() - blockHash := <-BlockHashCh2 - txHash := <-txHashCh2 - return blockHash, txHash, nil - -} - -func Bond(api *sdk.SubstrateAPI, seed string, WaitForInclusion sdk.WaitFor, amount int64, Payee sdk.Payee) (types.Hash, types.Hash, error) { - keyringPair, err := sdk.KeyringFromSeed(seed) - if err != nil { - panic(fmt.Sprintf("cannot create KeyPair:%v", err)) - } - bondAmount := sdk.ConvertToBondAmount(amount) - - newBondAmount := new(big.Int) - newBondAmount.Set(bondAmount) - - BlockHashCh2 := make(chan types.Hash) - txHashCh2 := make(chan types.Hash) - bondAmountUCompact := types.NewUCompact(newBondAmount) - go func() { - err = sdk.NewExtrinsicWatch(api, "Staking.bond", keyringPair, BlockHashCh2, txHashCh2, 0, WaitForInclusion, bondAmountUCompact, sdk.NewU8(Payee.EnumIndex())) - if err != nil { - fmt.Printf("cannot create extrinsic: %v", err) - close(BlockHashCh2) - close(txHashCh2) - return - } - - }() - blockHash := <-BlockHashCh2 - txHash := <-txHashCh2 - return blockHash, txHash, nil -} - -func BondExtra(api *sdk.SubstrateAPI, seed string, WaitForInclusion sdk.WaitFor, amount int64) (types.Hash, types.Hash, error) { - keyringPair, err := sdk.KeyringFromSeed(seed) - if err != nil { - panic(fmt.Sprintf("cannot create KeyPair:%v", err)) - } - BlockHashCh2 := make(chan types.Hash) - txHashCh2 := make(chan types.Hash) - bondAmount := sdk.ConvertToBondAmount(amount) - - newBondAmount := new(big.Int) - newBondAmount.Set(bondAmount) - bondAmountUCompact := types.NewUCompact(newBondAmount) - - go func() { - err = sdk.NewExtrinsicWatch(api, "Staking.bond_extra", keyringPair, BlockHashCh2, txHashCh2, 0, WaitForInclusion, bondAmountUCompact) - if err != nil { - fmt.Printf("cannot create extrinsic: %v", err) - close(BlockHashCh2) - close(txHashCh2) - return - } - - }() - blockHash := <-BlockHashCh2 - txHash := <-txHashCh2 - return blockHash, txHash, nil -} - -func Chill(api *sdk.SubstrateAPI, seed string, WaitForInclusion sdk.WaitFor) (types.Hash, types.Hash, error) { - keyringPair, err := sdk.KeyringFromSeed(seed) - if err != nil { - panic(fmt.Sprintf("cannot create KeyPair:%v", err)) - } - BlockHashCh2 := make(chan types.Hash) - txHashCh2 := make(chan types.Hash) - - go func() { - err = sdk.NewExtrinsicWatch(api, "Staking.chill", keyringPair, BlockHashCh2, txHashCh2, 0, WaitForInclusion) - if err != nil { - fmt.Printf("cannot create extrinsic: %v", err) - close(BlockHashCh2) - close(txHashCh2) - return - } - - }() - blockHash := <-BlockHashCh2 - txHash := <-txHashCh2 - return blockHash, txHash, nil -} - -func ChillOther(api *sdk.SubstrateAPI, seed string, WaitForInclusion sdk.WaitFor, stash string) (types.Hash, types.Hash, error) { - keyringPair, err := sdk.KeyringFromSeed(seed) - if err != nil { - panic(fmt.Sprintf("cannot create KeyPair:%v", err)) - } - fmt.Println(keyringPair) - _, pubkeyBytes, _ := subkey.SS58Decode(stash) - hexString := subkey.EncodeHex(pubkeyBytes) - - fmt.Println(hexString) - dest, err := sdk.NewMultiAddressFromHexAccountID(hexString) - if err != nil { - return types.Hash{}, types.Hash{}, err - } - fmt.Println(dest) - BlockHashCh2 := make(chan types.Hash) - txHashCh2 := make(chan types.Hash) - - go func() { - err = sdk.NewExtrinsicWatch(api, "Staking.chill_other", keyringPair, BlockHashCh2, txHashCh2, 0, WaitForInclusion, dest.AsID) - if err != nil { - fmt.Printf("cannot create extrinsic: %v", err) - close(BlockHashCh2) - close(txHashCh2) - return - } - - }() - blockHash := <-BlockHashCh2 - txHash := <-txHashCh2 - return blockHash, txHash, nil -} - -func Nominate(api *sdk.SubstrateAPI, seed string, WaitForInclusion sdk.WaitFor, stash []string) (types.Hash, types.Hash, error) { - keyringPair, err := sdk.KeyringFromSeed(seed) - if err != nil { - panic(fmt.Sprintf("cannot create KeyPair:%v", err)) - } - var dest []types.MultiAddress - for _, v := range stash { - _, pubkeyBytes, _ := subkey.SS58Decode(v) - hexString := subkey.EncodeHex(pubkeyBytes) - d, err := sdk.NewMultiAddressFromHexAccountID(hexString) - if err != nil { - return types.Hash{}, types.Hash{}, err - } - dest = append(dest, d) - } - - BlockHashCh2 := make(chan types.Hash) - txHashCh2 := make(chan types.Hash) - - go func() { - err = sdk.NewExtrinsicWatch(api, "Staking.nominate", keyringPair, BlockHashCh2, txHashCh2, 0, WaitForInclusion, dest) - if err != nil { - fmt.Printf("cannot create extrinsic: %v", err) - close(BlockHashCh2) - close(txHashCh2) - return - } - - }() - blockHash := <-BlockHashCh2 - txHash := <-txHashCh2 - return blockHash, txHash, nil -} - -func Unbond(api *sdk.SubstrateAPI, seed string, WaitForInclusion sdk.WaitFor, amount types.UCompact) (types.Hash, types.Hash, error) { - keyringPair, err := sdk.KeyringFromSeed(seed) - if err != nil { - panic(fmt.Sprintf("cannot create KeyPair:%v", err)) - } - BlockHashCh2 := make(chan types.Hash) - txHashCh2 := make(chan types.Hash) - - go func() { - err = sdk.NewExtrinsicWatch(api, "Staking.unbond", keyringPair, BlockHashCh2, txHashCh2, 0, WaitForInclusion, amount) - if err != nil { - fmt.Printf("cannot create extrinsic: %v", err) - close(BlockHashCh2) - close(txHashCh2) - return - } - - }() - blockHash := <-BlockHashCh2 - txHash := <-txHashCh2 - return blockHash, txHash, nil -} - -func Validate(api *sdk.SubstrateAPI, seed string, WaitForInclusion sdk.WaitFor, commissionNum int) (types.Hash, types.Hash, error) { - keyringPair, err := sdk.KeyringFromSeed(seed) - if err != nil { - panic(fmt.Sprintf("cannot create KeyPair:%v", err)) - } - BlockHashCh2 := make(chan types.Hash) - txHashCh2 := make(chan types.Hash) - commissionStr, err := commissionNumberToPerbill(commissionNum) - if err != nil { - fmt.Errorf("failed to convert commission to Perbill: %v", err) - } - - commission, err := strconv.ParseUint(commissionStr, 10, 64) - if err != nil { - fmt.Errorf("failed to parse commission string: %v", err) - } - - // Define the ValidatorPrefs struct manually - type ValidatorPrefs struct { - Commission types.UCompact - Blocked bool - } - - // Create the validator preferences struct - prefs := ValidatorPrefs{ - Commission: types.NewUCompactFromUInt(commission), - Blocked: false, - } - go func() { - err = sdk.NewExtrinsicWatch(api, "Staking.validate", keyringPair, BlockHashCh2, txHashCh2, 0, WaitForInclusion, prefs) - if err != nil { - fmt.Printf("cannot create extrinsic: %v", err) - close(BlockHashCh2) - close(txHashCh2) - return - } - - }() - blockHash := <-BlockHashCh2 - txHash := <-txHashCh2 - return blockHash, txHash, nil -} - -func commissionNumberToPerbill(value int) (string, error) { - if value < 0 || value > 100 { - return "", errors.New("Commission is limited to the following range: 0 - 100. It cannot be less than 0 or more than 100.") - } - - commission := strconv.Itoa(value) + "0000000" - // For some reason 0 commission is not defined as "0" but as "1". - if commission == "00000000" { - commission = "1" - } - - return commission, nil -} - -func TransferKeepAlive(api *sdk.SubstrateAPI, seed string, WaitForInclusion sdk.WaitFor, dest string, amount types.UCompact) (types.Hash, types.Hash, error) { - keyringPair, err := sdk.KeyringFromSeed(seed) - if err != nil { - panic(fmt.Sprintf("cannot create KeyPair:%v", err)) - } - _, pubkeyBytes, _ := subkey.SS58Decode(dest) - hexString := subkey.EncodeHex(pubkeyBytes) - destAddr, err := sdk.NewMultiAddressFromHexAccountID(hexString) - if err != nil { - return types.Hash{}, types.Hash{}, err - } - BlockHashCh2 := make(chan types.Hash) - txHashCh2 := make(chan types.Hash) - - go func() { - err = sdk.NewExtrinsicWatch(api, "Balances.transfer_keep_alive", keyringPair, BlockHashCh2, txHashCh2, 0, WaitForInclusion, destAddr, amount) - if err != nil { - fmt.Printf("cannot create extrinsic: %v", err) - close(BlockHashCh2) - close(txHashCh2) - return - } - fmt.Println("Transaction submitted successfully") - }() - blockHash := <-BlockHashCh2 - txHash := <-txHashCh2 - return blockHash, txHash, nil -} - -func TransferAllowDeath(api *sdk.SubstrateAPI, seed string, WaitForInclusion sdk.WaitFor, dest string, amount types.UCompact) (types.Hash, types.Hash, error) { - keyringPair, err := sdk.KeyringFromSeed(seed) - if err != nil { - panic(fmt.Sprintf("cannot create KeyPair:%v", err)) - } - _, pubkeyBytes, _ := subkey.SS58Decode(dest) - hexString := subkey.EncodeHex(pubkeyBytes) - destAddr, err := sdk.NewMultiAddressFromHexAccountID(hexString) - if err != nil { - return types.Hash{}, types.Hash{}, err - } - BlockHashCh2 := make(chan types.Hash) - txHashCh2 := make(chan types.Hash) - - go func() { - err = sdk.NewExtrinsicWatch(api, "Balances.transfer_allow_death", keyringPair, BlockHashCh2, txHashCh2, 0, WaitForInclusion, destAddr, amount) - if err != nil { - fmt.Printf("cannot create extrinsic: %v", err) - close(BlockHashCh2) - close(txHashCh2) - return - } - fmt.Println("Transaction submitted successfully") - }() - blockHash := <-BlockHashCh2 - txHash := <-txHashCh2 - return blockHash, txHash, nil -} - -func TransferAll(api *sdk.SubstrateAPI, seed string, WaitForInclusion sdk.WaitFor, dest string) (types.Hash, types.Hash, error) { - keyringPair, err := sdk.KeyringFromSeed(seed) - if err != nil { - panic(fmt.Sprintf("cannot create KeyPair:%v", err)) - } - _, pubkeyBytes, _ := subkey.SS58Decode(dest) - hexString := subkey.EncodeHex(pubkeyBytes) - destAddr, err := sdk.NewMultiAddressFromHexAccountID(hexString) - if err != nil { - return types.Hash{}, types.Hash{}, err - } - BlockHashCh2 := make(chan types.Hash) - txHashCh2 := make(chan types.Hash) - - go func() { - err = sdk.NewExtrinsicWatch(api, "Balances.transfer_all", keyringPair, BlockHashCh2, txHashCh2, 0, WaitForInclusion, destAddr, sdk.NewU8(1)) //KeepAlive:yes, change to 0 for no - if err != nil { - fmt.Printf("cannot create extrinsic: %v", err) - close(BlockHashCh2) - close(txHashCh2) - return - } - fmt.Println("Transaction submitted successfully") - }() - blockHash := <-BlockHashCh2 - txHash := <-txHashCh2 - return blockHash, txHash, nil -} diff --git a/src/sdk/types/types.go b/src/sdk/types/types.go deleted file mode 100644 index 4eca8f4..0000000 --- a/src/sdk/types/types.go +++ /dev/null @@ -1,24 +0,0 @@ -package types - -import ( - "github.com/centrifuge/go-substrate-rpc-client/v4/types" -) - -type MultiAddress = types.MultiAddress - -type Call = types.Call -type Metadata = types.Metadata -type Hash = types.Hash -type U32 = types.U32 -type U264 = types.U64 -type U256 = types.U256 -type U128 = types.U128 -type Weight = types.Weight -type DispatchClass = types.DispatchClass -type PartialFee = types.UCompact -type ChainProperties struct { - IsEthereum bool - SS58Format types.U32 - TokenDecimals types.U32 - TokenSymbol types.Text -} diff --git a/src/sdk/types/ucompact.go b/src/sdk/types/ucompact.go deleted file mode 100644 index 2e5e415..0000000 --- a/src/sdk/types/ucompact.go +++ /dev/null @@ -1,54 +0,0 @@ -package types - -import ( - "encoding/json" - "math/big" - - "github.com/centrifuge/go-substrate-rpc-client/v4/scale" -) - -type UCompact big.Int - -func NewUCompact(value *big.Int) UCompact { - return UCompact(*value) -} - -func (u *UCompact) Int64() int64 { - i := big.Int(*u) - return i.Int64() -} - -func NewUCompactFromUInt(value uint64) UCompact { - return NewUCompact(new(big.Int).SetUint64(value)) -} - -func (u *UCompact) Decode(decoder scale.Decoder) error { - ui, err := decoder.DecodeUintCompact() - if err != nil { - return err - } - - *u = UCompact(*ui) - return nil -} - -func (u UCompact) Encode(encoder scale.Encoder) error { - err := encoder.EncodeUintCompact(big.Int(u)) - if err != nil { - return err - } - return nil -} - -func (u UCompact) MarshalJSON() ([]byte, error) { - return json.Marshal(u.Int64()) -} - -func (u *UCompact) UnmarshalJSON(b []byte) error { - var i big.Int - if err := json.Unmarshal(b, &i); err != nil { - return err - } - *u = UCompact(i) - return nil -} From 6dfaf4b8c611426644d5319ae14ff0487cff0772 Mon Sep 17 00:00:00 2001 From: Marko Petrlic Date: Thu, 16 Jan 2025 12:13:26 +0100 Subject: [PATCH 2/3] Added constants for existing networks. --- main.go | 84 ++++++++++++--------------------------------------------- sdk.go | 13 +++++++++ 2 files changed, 30 insertions(+), 67 deletions(-) diff --git a/main.go b/main.go index 78a2135..6b45250 100644 --- a/main.go +++ b/main.go @@ -1,80 +1,30 @@ package main import ( - // Complex "go-sdk/complex" - // "go-sdk/metadata" - // Balances "go-sdk/metadata/pallets/balances" + "github.com/vedhavyas/go-subkey/v2" + "github.com/vedhavyas/go-subkey/v2/sr25519" "go-sdk/complex" - "go-sdk/primitives" - "sync" - "time" - // "github.com/vedhavyas/go-subkey/v2" - // "github.com/vedhavyas/go-subkey/v2/sr25519" + Balances "go-sdk/metadata/pallets/balances" ) -func Job(targetBlockNumber uint32, wg *sync.WaitGroup) { - sdk := NewSDK2("https://mainnet-rpc.avail.so/rpc") - targetBlockHash := sdk.Client.Rpc.Chain.GetBlockHash(primitives.NewSome(targetBlockNumber)) - println("Block Number:", targetBlockNumber, "Block Hash: ", targetBlockHash.ToHexWith0x()) - - targetBlockHash2 := targetBlockHash - /* - Turing - if targetBlockNumber == 297282 { - targetBlockHash2 = sdk.Client.Rpc.Chain.GetBlockHash(primitives.NewSome(targetBlockNumber - 1)) - } - */ - if err := sdk.Client.InitMetadata(primitives.NewSome(targetBlockHash2)); err != nil { - panic(err) - } - - // Decoding Extrinsics and Events - complex.NewBlock(sdk.Client, targetBlockHash) - wg.Done() -} - func main() { - sdk := NewSDK2("https://mainnet-rpc.avail.so/rpc") - println("Genesis: ", sdk.Client.Rpc.Chain.GetBlockHash(primitives.NewSome(uint32(0))).ToHexWith0x()) - - targetBlockNumber := uint32(246585) - var wg sync.WaitGroup - for { - for i := 1; i <= 100; i++ { - wg.Add(1) - go Job(targetBlockNumber, &wg) - targetBlockNumber += 1 - } - - wg.Wait() - time.Sleep(time.Millisecond * 50) - } - - /* - // Go through blocks and see which one is not decodable - - add, err := metadata.NewAccountIdFromAddress("5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY") - if err != nil { - panic(err) - } - println(add.ToHuman()) + sdk := NewSDK(LocalEndpoint) + uri := "bottom drive obey lake curtain smoke basket hold race lonely fit walk//Alice" + scheme := new(sr25519.Scheme) + account, _ := subkey.DeriveKeyPair(scheme, uri) - uri := "bottom drive obey lake curtain smoke basket hold race lonely fit walk//Alice" - scheme := new(sr25519.Scheme) - account, _ := subkey.DeriveKeyPair(scheme, uri) + var tx = sdk.Tx.DataAvailability.SubmitData([]byte("aabbcc")) + var options = complex.NewTransactionOptions().WithAppId(uint32(1)) - var tx = sdk.Tx.DataAvailability.SubmitData([]byte("aabbcc")) - var options = Complex.NewTransactionOptions().WithAppId(uint32(1)) + var details = tx.ExecuteAndWatch(account, false, options) + println("Block Hash: ", details.BlockHash.ToHexWith0x()) + println("Block Number: ", details.BlockNumber) + println("TX Events ", len(details.Events.Unwrap())) - var details = tx.ExecuteAndWatch(account, false, options) - println("Block Hash: ", details.BlockHash.ToHexWith0x()) - println("Block Number: ", details.BlockNumber) - println("TX Events ", len(details.Events.Unwrap())) + var events = details.Events.UnwrapOrDefault() - var eves = details.Events.Unwrap() + var event = complex.FindFirst(events, Balances.EventWithdraw{}).UnwrapOrDefault() + println("Who:", event.Who.ToHuman()) + println("Amount: ", event.Amount.ToHuman()) - var res = Complex.FindFirst(eves, Balances.EventWithdraw{}) - println("Who:", res.Unwrap().Who.ToHuman()) - println("Amount: ", res.Unwrap().Amount.ToHuman()) - */ } diff --git a/sdk.go b/sdk.go index b5e69dc..8ed5636 100644 --- a/sdk.go +++ b/sdk.go @@ -4,6 +4,9 @@ import ( Complex "go-sdk/complex" DA "go-sdk/metadata/pallets/data_availability" Prim "go-sdk/primitives" + "math/big" + + "github.com/itering/scale.go/utiles/uint128" ) type SDK struct { @@ -20,6 +23,7 @@ func NewSDK(endpoint string) SDK { } } +// Temp for testing func NewSDK2(endpoint string) SDK { var client = Complex.NewClient(endpoint) return SDK{ @@ -49,3 +53,12 @@ func (this *DataAvailabilityTx) SubmitData(data []byte) Complex.Transaction { } return Complex.NewTransaction(this.Client, call.ToPayload()) } + +func OneAvail() uint128.Uint128 { + var res, _ = new(big.Int).SetString("1000000000000000000", 10) + return uint128.FromBig(res) +} + +const LocalEndpoint = "http://127.0.0.1:9944" +const TuringEndpoint = "https://turing-rpc.avail.so/rpc" +const MainnetEndpoint = "https://mainnet-rpc.avail.so/rpc" From 6a633da21a7b88f509a1c7dbaacd1e6ca5d54990 Mon Sep 17 00:00:00 2001 From: Marko Petrlic Date: Thu, 16 Jan 2025 12:25:13 +0100 Subject: [PATCH 3/3] Removed linter --- .github/workflows/lint.yml | 27 --------------------------- 1 file changed, 27 deletions(-) delete mode 100644 .github/workflows/lint.yml diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml deleted file mode 100644 index 2a3e41e..0000000 --- a/.github/workflows/lint.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Go Lint - -on: - push: - branches: [main] - pull_request: - branches: [main] - -jobs: - lint: - name: Lint - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - name: Set up Go - uses: actions/setup-go@v4 - with: - go-version: "1.21" # You can adjust this to your project's Go version - - - name: Install golangci-lint - run: | - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.55.2 - golangci-lint --version - - - name: Run golangci-lint - run: golangci-lint run --timeout=5m