Skip to content

Instantly share code, notes, and snippets.

@Mleekko
Created July 10, 2022 06:57
Show Gist options
  • Save Mleekko/94f29c1636fe6a01b470584b0e891476 to your computer and use it in GitHub Desktop.
Save Mleekko/94f29c1636fe6a01b470584b0e891476 to your computer and use it in GitHub Desktop.
Transaction signing in go
package main
import (
"bytes"
"crypto/ecdsa"
"encoding/hex"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"math/big"
"net/http"
"strings"
bech32x "github.com/btcsuite/btcutil/bech32"
"github.com/ethereum/go-ethereum/crypto"
"golang.org/x/crypto/cryptobyte"
"golang.org/x/crypto/cryptobyte/asn1"
)
var (
seckey *ecdsa.PrivateKey
)
func main() {
seckey, _ = crypto.HexToECDSA("1010101010101010101010101010101010101010101010101010101010101010")
pubkey := crypto.CompressPubkey(&seckey.PublicKey)
pub := append([]byte{0x04}, pubkey...)
c, err := bech32x.ConvertBits(pub, 8, 5, true)
if err != nil {
log.Fatal(err)
}
d, err := bech32x.Encode("rdx", c)
if err != nil {
log.Fatal(err)
}
log.Println("From Addr: " + d)
jsonStr := []byte(`{
"network_identifier": {
"network": "mainnet"
},
"actions": [
{
"type": "TransferTokens",
"from_account": {
"address": "` + d + `"
},
"to_account": {
"address": "rdx1qsp94jxvj4jwswx3mzvsdlh8cl7fasnnsnqzhch37v6ckssdku948ygy5y3uq"
},
"amount": {
"token_identifier": {
"rri": "xrd_rr1qy5wfsfh"
},
"value": "100000000000000000"
}
}
],
"fee_payer": {
"address": "` + d + `"
},
"disable_token_mint_and_burn": true
}`)
req, err := http.NewRequest("POST", "https://api.radix.live/transaction/build", bytes.NewBuffer(jsonStr))
if err != nil {
log.Fatal(err)
}
req.Header.Set("x-radixdlt-target-gw-api", "1.1.2")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println("response Status:", resp.Status)
// fmt.Println("response Headers:", resp.Header)
body, _ := ioutil.ReadAll(resp.Body)
if !strings.Contains(resp.Status, "200") {
log.Fatal(string(body))
}
var root map[string]interface{}
json.Unmarshal(body, &root)
txBuild := root["transaction_build"].(map[string]interface{})
strUnsignedTx := txBuild["unsigned_transaction"].(string)
strPayload := txBuild["payload_to_sign"].(string)
fmt.Println("unsigned tx: ", strUnsignedTx)
fmt.Println("payload: ", strPayload)
hashToSign, _ := hex.DecodeString(strPayload)
fmt.Printf("hashToSign length: %v\n", len(strPayload))
signature, err := crypto.Sign(hashToSign, seckey)
if err != nil {
log.Fatal(err)
}
rVal := new(big.Int)
rVal.SetBytes(signature[0:32])
sVal := new(big.Int)
sVal.SetBytes(signature[32:64])
var b cryptobyte.Builder
b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) {
b.AddASN1BigInt(rVal)
b.AddASN1BigInt(sVal)
})
signatureDER, _ := b.Bytes()
strSig := hex.EncodeToString(signatureDER)
jsonStr = []byte(`{
"network_identifier": {
"network": "mainnet"
},
"unsigned_transaction": "` + strUnsignedTx + `",
"signature": {
"bytes": "` + strSig + `",
"public_key": {
"hex": "` + hex.EncodeToString(pubkey) + `"
}
}
}`)
req, err = http.NewRequest("POST", "https://api.radix.live/transaction/finalize", bytes.NewBuffer(jsonStr))
if err != nil {
log.Fatal(err)
}
req.Header.Set("x-radixdlt-target-gw-api", "1.1.2")
req.Header.Set("Content-Type", "application/json")
client = &http.Client{}
resp, err = client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println("response Status:", resp.Status)
fmt.Println("response Headers:", resp.Header)
body, _ = ioutil.ReadAll(resp.Body)
fmt.Println("response Body:", string(body))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment