Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[refactor] Make things more Go like #26

Merged
merged 10 commits into from
May 14, 2024
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
# Aptos Go SDK Changelog

All notable changes to the Aptos Go SDK will be captured in this file. This changelog is written by hand for now. It adheres to the format set out by [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
All notable changes to the Aptos Go SDK will be captured in this file. This changelog is written by hand for now. It
adheres to the format set out by [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

# Unreleased

- Refactored all pieces into new packages, this may break previous users
- [`Fix`] Misspelling of expiration time
- Added documentation for many functions and structs

# v0.1.0 (5/7/2024)

- Ed25519 support
- Ed25519 transaction support
- View function support
Expand Down
4 changes: 2 additions & 2 deletions core/account.go → account.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package core
package aptos

import (
"crypto/rand"
Expand All @@ -7,7 +7,7 @@ import (
"fmt"
"github.com/aptos-labs/aptos-go-sdk/bcs"
"github.com/aptos-labs/aptos-go-sdk/crypto"
"github.com/aptos-labs/aptos-go-sdk/util"
"github.com/aptos-labs/aptos-go-sdk/internal/util"
"strings"
)

Expand Down
4 changes: 3 additions & 1 deletion accountResourceRecord.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package aptos

import "github.com/aptos-labs/aptos-go-sdk/bcs"
import (
"github.com/aptos-labs/aptos-go-sdk/bcs"
)

// AccountResourceRecord DeserializeSequence[AccountResourceRecord](bcs) approximates the Rust side BTreeMap<StructTag,Vec<u8>>
// They should BCS the same with a prefix Uleb128 length followed by (StructTag,[]byte) pairs.
Expand Down
2 changes: 1 addition & 1 deletion core/account_test.go → account_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package core
package aptos

import (
"github.com/stretchr/testify/assert"
Expand Down
15 changes: 7 additions & 8 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package aptos

import (
"errors"
"github.com/aptos-labs/aptos-go-sdk/core"
"time"
)

Expand Down Expand Up @@ -117,24 +116,24 @@ func (client *Client) Info() (info NodeInfo, err error) {
}

// Account Retrieves information about the account such as SequenceNumber and AuthenticationKey
func (client *Client) Account(address core.AccountAddress, ledgerVersion ...int) (info AccountInfo, err error) {
func (client *Client) Account(address AccountAddress, ledgerVersion ...int) (info AccountInfo, err error) {
return client.nodeClient.Account(address, ledgerVersion...)
}

// AccountResource Retrieves a single resource given its struct name.
// Can also fetch at a specific ledger version
func (client *Client) AccountResource(address core.AccountAddress, resourceType string, ledgerVersion ...int) (data map[string]any, err error) {
func (client *Client) AccountResource(address AccountAddress, resourceType string, ledgerVersion ...int) (data map[string]any, err error) {
return client.nodeClient.AccountResource(address, resourceType, ledgerVersion...)
}

// AccountResources fetches resources for an account into a JSON-like map[string]any in AccountResourceInfo.Data
// For fetching raw Move structs as BCS, See #AccountResourcesBCS
func (client *Client) AccountResources(address core.AccountAddress, ledgerVersion ...int) (resources []AccountResourceInfo, err error) {
func (client *Client) AccountResources(address AccountAddress, ledgerVersion ...int) (resources []AccountResourceInfo, err error) {
return client.nodeClient.AccountResources(address, ledgerVersion...)
}

// AccountResourcesBCS fetches account resources as raw Move struct BCS blobs in AccountResourceRecord.Data []byte
func (client *Client) AccountResourcesBCS(address core.AccountAddress, ledgerVersion ...int) (resources []AccountResourceRecord, err error) {
func (client *Client) AccountResourcesBCS(address AccountAddress, ledgerVersion ...int) (resources []AccountResourceRecord, err error) {
return client.nodeClient.AccountResourcesBCS(address, ledgerVersion...)
}

Expand Down Expand Up @@ -193,19 +192,19 @@ func (client *Client) GetChainId() (chainId uint8, err error) {
}

// Fund Uses the faucet to fund an address, only applies to non-production networks
func (client *Client) Fund(address core.AccountAddress, amount uint64) error {
func (client *Client) Fund(address AccountAddress, amount uint64) error {
return client.faucetClient.Fund(address, amount)
}

// BuildTransaction Builds a raw transaction from the payload and fetches any necessary information
// from onchain
func (client *Client) BuildTransaction(sender core.AccountAddress, payload TransactionPayload, options ...any) (rawTxn *RawTransaction, err error) {
func (client *Client) BuildTransaction(sender AccountAddress, payload TransactionPayload, options ...any) (rawTxn *RawTransaction, err error) {
return client.nodeClient.BuildTransaction(sender, payload, options...)
}

// BuildSignAndSubmitTransaction Convenience function to do all three in one
// for more configuration, please use them separately
func (client *Client) BuildSignAndSubmitTransaction(sender *core.Account, payload TransactionPayload, options ...any) (hash string, err error) {
func (client *Client) BuildSignAndSubmitTransaction(sender *Account, payload TransactionPayload, options ...any) (hash string, err error) {
return client.nodeClient.BuildSignAndSubmitTransaction(sender, payload, options...)
}

Expand Down
9 changes: 4 additions & 5 deletions client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package aptos

import (
"github.com/aptos-labs/aptos-go-sdk/bcs"
"github.com/aptos-labs/aptos-go-sdk/core"
"strconv"
"testing"

Expand Down Expand Up @@ -38,7 +37,7 @@ func Test_Flow(t *testing.T) {
assert.Less(t, uint8(4), chainId)

// Create an account
account, err := core.NewEd25519Account()
account, err := NewEd25519Account()
assert.NoError(t, err)

// Fund the account with 1 APT
Expand All @@ -47,7 +46,7 @@ func Test_Flow(t *testing.T) {

// Send money to 0x1
// Build transaction
signed_txn, err := APTTransferTransaction(client, account, core.AccountOne, 100)
signed_txn, err := APTTransferTransaction(client, account, AccountOne, 100)
assert.NoError(t, err)

serializer := bcs.Serializer{}
Expand Down Expand Up @@ -82,9 +81,9 @@ func Test_Flow(t *testing.T) {
}

func TestAPTTransferTransaction(t *testing.T) {
sender, err := core.NewEd25519Account()
sender, err := NewEd25519Account()
assert.NoError(t, err)
dest, err := core.NewEd25519Account()
dest, err := NewEd25519Account()
assert.NoError(t, err)

client, err := NewClient(DevnetConfig)
Expand Down
5 changes: 2 additions & 3 deletions client_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package aptos
import (
"encoding/binary"
"fmt"
"github.com/aptos-labs/aptos-go-sdk/core"
"net/url"
"runtime/debug"
)
Expand Down Expand Up @@ -51,14 +50,14 @@ func init() {
// Amount in Octas (10^-8 APT)
//
// options may be: MaxGasAmount, GasUnitPrice, ExpirationSeconds, ValidUntil, SequenceNumber, ChainIdOption
func APTTransferTransaction(client *Client, sender *core.Account, dest core.AccountAddress, amount uint64, options ...any) (signedTxn *SignedTransaction, err error) {
func APTTransferTransaction(client *Client, sender *Account, dest AccountAddress, amount uint64, options ...any) (signedTxn *SignedTransaction, err error) {
var amountBytes [8]byte
binary.LittleEndian.PutUint64(amountBytes[:], amount)

rawTxn, err := client.BuildTransaction(sender.Address,
TransactionPayload{Payload: &EntryFunction{
Module: ModuleId{
Address: core.AccountOne,
Address: AccountOne,
Name: "aptos_account",
},
Function: "transfer",
Expand Down
28 changes: 13 additions & 15 deletions cmd/goclient/goclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,14 @@ import (
"encoding/hex"
"encoding/json"
"fmt"
"github.com/aptos-labs/aptos-go-sdk/core"
"github.com/aptos-labs/aptos-go-sdk"
"log/slog"
"net/url"
"os"
"runtime/debug"
"strconv"
"strings"
"time"

aptos "github.com/aptos-labs/aptos-go-sdk"
)

var (
Expand Down Expand Up @@ -124,7 +122,7 @@ func main() {
maybefail(err, "client error: %s", err)
}

var account core.AccountAddress
var account aptos.AccountAddress
if accountStr != "" {
err := account.ParseStringRelaxed(accountStr)
maybefail(err, "could not parse address: %s", err)
Expand Down Expand Up @@ -208,14 +206,14 @@ func main() {
}
os.Stdout.WriteString(prettyJson(data))
} else if arg == "naf" {
alice, err := core.NewEd25519Account()
alice, err := aptos.NewEd25519Account()
maybefail(err, "new account: %s", err)
amount := uint64(200_000_000)
err = client.Fund(alice.Address, amount)
maybefail(err, "faucet err: %s", err)
fmt.Fprintf(os.Stdout, "new account %s funded for %d\n", alice.Address.String(), amount)

bob, err := core.NewEd25519Account()
bob, err := aptos.NewEd25519Account()
maybefail(err, "new account: %s", err)
//amount = uint64(10_000_000)
err = client.Fund(bob.Address, amount)
Expand Down Expand Up @@ -253,8 +251,8 @@ func main() {
fmt.Printf("bob addr %s\n", bob.Address.String())
} else if arg == "send" {
// next three args: source addr, dest addr, amount
var sender core.AccountAddress
var dest core.AccountAddress
var sender aptos.AccountAddress
var dest aptos.AccountAddress
var amount uint64
err := sender.ParseStringRelaxed(misc[argi+1])
maybefail(err, "bad sender, %s", err)
Expand Down Expand Up @@ -282,7 +280,7 @@ func main() {
SequenceNumber: sn + 1,
Payload: aptos.TransactionPayload{Payload: &aptos.EntryFunction{
Module: aptos.ModuleId{
Address: core.AccountOne,
Address: aptos.AccountOne,
Name: "aptos_account",
},
Function: "transfer",
Expand All @@ -296,13 +294,13 @@ func main() {
amountbytes[:],
},
}},
MaxGasAmount: 1000,
GasUnitPrice: 2000,
ExpirationTimetampSeconds: uint64(now + 100),
ChainId: 4,
MaxGasAmount: 1000,
GasUnitPrice: 2000,
ExpirationTimestampSeconds: uint64(now + 100),
ChainId: 4,
}
txnblob, err := txn.SignableBytes()
maybefail(err, "txn SignableBytes, %s", err)
txnblob, err := txn.SigningMessage()
maybefail(err, "txn SigningMessage, %s", err)
//ser := aptos.Serializer{}
//txn.MarshalBCS(&ser)
//err = ser.Error()
Expand Down
48 changes: 11 additions & 37 deletions crypto/authenticator.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package crypto

import (
"crypto/ed25519"
"fmt"

"github.com/aptos-labs/aptos-go-sdk/bcs"
Expand Down Expand Up @@ -29,6 +28,15 @@ const (
AuthenticatorSingleSender AuthenticatorType = 4
)

// AuthenticatorImpl an implementation of an authenticator to provide generic verification across multiple types
type AuthenticatorImpl interface {
bcs.Struct

// Verify Return true if this Authenticator approves
Verify(data []byte) bool
}

// Authenticator a generic authenticator type for a transaction
type Authenticator struct {
Kind AuthenticatorType
Auth AuthenticatorImpl
Expand All @@ -38,6 +46,7 @@ func (ea *Authenticator) MarshalBCS(bcs *bcs.Serializer) {
bcs.Uleb128(uint32(ea.Kind))
ea.Auth.MarshalBCS(bcs)
}

func (ea *Authenticator) UnmarshalBCS(bcs *bcs.Deserializer) {
kindu := bcs.Uleb128()
if bcs.Error() != nil {
Expand All @@ -54,44 +63,9 @@ func (ea *Authenticator) UnmarshalBCS(bcs *bcs.Deserializer) {
}
}

// Verify verifies a message with the public key and signature
func (ea *Authenticator) Verify(data []byte) bool {
return ea.Auth.Verify(data)
}

type AuthenticatorImpl interface {
bcs.Struct

// Verify Return true if this Authenticator approves
Verify(data []byte) bool
}

type Ed25519Authenticator struct {
PublicKey [ed25519.PublicKeySize]byte
Signature [ed25519.SignatureSize]byte
}

func (ea *Ed25519Authenticator) MarshalBCS(bcs *bcs.Serializer) {
bcs.WriteBytes(ea.PublicKey[:])
bcs.WriteBytes(ea.Signature[:])
}
func (ea *Ed25519Authenticator) UnmarshalBCS(bcs *bcs.Deserializer) {
kb := bcs.ReadBytes()
if len(kb) != ed25519.PublicKeySize {
bcs.SetError(fmt.Errorf("bad ed25519 public key, expected %d bytes but got %d", ed25519.PublicKeySize, len(kb)))
return
}
sb := bcs.ReadBytes()
if len(sb) != ed25519.SignatureSize {
bcs.SetError(fmt.Errorf("bad ed25519 signature, expected %d bytes but got %d", ed25519.SignatureSize, len(sb)))
return
}
copy(ea.PublicKey[:], kb)
copy(ea.Signature[:], sb)
}

// Verify Return true if the data was well signed
func (ea *Ed25519Authenticator) Verify(data []byte) bool {
return ed25519.Verify(ed25519.PublicKey(ea.PublicKey[:]), data, ea.Signature[:])
}

// TODO: FeePayerAuthenticator, MultiAgentAuthenticator, MultiEd25519Authenticator, SingleSenderAuthenticator, SingleKeyAuthenticator
33 changes: 32 additions & 1 deletion crypto/ed25519.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import (
"crypto/ed25519"
"encoding/hex"
"errors"
"github.com/aptos-labs/aptos-go-sdk/util"
"fmt"
"github.com/aptos-labs/aptos-go-sdk/bcs"
"github.com/aptos-labs/aptos-go-sdk/internal/util"
)

type Ed25519PrivateKey struct {
Expand Down Expand Up @@ -89,3 +91,32 @@ func (key *Ed25519PublicKey) FromHex(hexStr string) (err error) {
key.inner = bytes
return nil
}

type Ed25519Authenticator struct {
PublicKey [ed25519.PublicKeySize]byte
Signature [ed25519.SignatureSize]byte
}

func (ea *Ed25519Authenticator) MarshalBCS(bcs *bcs.Serializer) {
bcs.WriteBytes(ea.PublicKey[:])
bcs.WriteBytes(ea.Signature[:])
}
func (ea *Ed25519Authenticator) UnmarshalBCS(bcs *bcs.Deserializer) {
kb := bcs.ReadBytes()
if len(kb) != ed25519.PublicKeySize {
bcs.SetError(fmt.Errorf("bad ed25519 public key, expected %d bytes but got %d", ed25519.PublicKeySize, len(kb)))
return
}
sb := bcs.ReadBytes()
if len(sb) != ed25519.SignatureSize {
bcs.SetError(fmt.Errorf("bad ed25519 signature, expected %d bytes but got %d", ed25519.SignatureSize, len(sb)))
return
}
copy(ea.PublicKey[:], kb)
copy(ea.Signature[:], sb)
}

// Verify Return true if the data was well signed
func (ea *Ed25519Authenticator) Verify(data []byte) bool {
return ed25519.Verify(ed25519.PublicKey(ea.PublicKey[:]), data, ea.Signature[:])
}
Loading