Skip to content

Commit

Permalink
Merge pull request #5 from gagliardetto/token-2
Browse files Browse the repository at this point in the history
- Add client for token program.
- Add SendAndConfirmTransaction.
- Improve formatting of parsed transactions.
  • Loading branch information
gagliardetto authored Sep 6, 2021
2 parents 17d74ec + 18f8518 commit be93bc0
Show file tree
Hide file tree
Showing 80 changed files with 5,715 additions and 610 deletions.
18 changes: 14 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Solana SDK library for Go

[![GoDoc](https://pkg.go.dev/badge/github.com/gagliardetto/solana-go?status.svg)](https://pkg.go.dev/github.com/gagliardetto/[email protected].3?tab=doc)
[![GoDoc](https://pkg.go.dev/badge/github.com/gagliardetto/solana-go?status.svg)](https://pkg.go.dev/github.com/gagliardetto/[email protected].4?tab=doc)
[![GitHub tag (latest SemVer pre-release)](https://img.shields.io/github/v/tag/gagliardetto/solana-go?include_prereleases&label=release-tag)](https://github.com/gagliardetto/solana-go/releases)
[![Build Status](https://github.com/gagliardetto/solana-go/workflows/tests/badge.svg?branch=main)](https://github.com/gagliardetto/solana-go/actions?query=branch%3Amain)
[![TODOs](https://badgen.net/https/api.tickgit.com/badgen/github.com/gagliardetto/solana-go/main)](https://www.tickgit.com/browse?repo=github.com/gagliardetto/solana-go&branch=main)
Expand Down Expand Up @@ -41,13 +41,23 @@ More contracts to come.
- [x] Full WebSocket JSON streaming API
- [ ] Wallet, account, and keys management
- [ ] Clients for native programs
- [ ] Clients for Solana Program Library
- [x] system
- [ ] config
- [ ] stake
- [ ] vote
- [ ] BPF Loader
- [ ] Secp256k1
- [ ] Clients for Solana Program Library (SPL)
- [ ] token: WIP
- [ ] memo
- [ ] name-service
- [ ] ...
- [ ] Client for Serum
- [ ] More programs

## Current development status

There is currently **no stable release**. The SDK is actively developed and latest is `v0.4.3` which is an `alpha` release.
There is currently **no stable release**. The SDK is actively developed and latest is `v0.4.4` which is an `alpha` release.

The RPC and WS client implementation is based on [this RPC spec](https://github.com/solana-labs/solana/blob/dff9c88193da142693cabebfcd3bf68fa8e8b873/docs/src/developing/clients/jsonrpc-api.md).

Expand All @@ -61,7 +71,7 @@ The RPC and WS client implementation is based on [this RPC spec](https://github.
```bash
$ cd my-project
$ go get github.com/gagliardetto/[email protected].3
$ go get github.com/gagliardetto/[email protected].4
$ go get github.com/gagliardetto/[email protected]
$ go get github.com/gagliardetto/[email protected]
```
Expand Down
36 changes: 36 additions & 0 deletions account.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,39 @@ func (slice AccountMetaSlice) GetSigners() []*AccountMeta {
}
return signers
}

func (slice AccountMetaSlice) Len() int {
return len(slice)
}

func (slice AccountMetaSlice) SplitFrom(index int) (AccountMetaSlice, AccountMetaSlice) {
if index < 0 {
panic("negative index")
}
if index == 0 {
return AccountMetaSlice{}, slice
}
if index > len(slice)-1 {
return slice, AccountMetaSlice{}
}

firstLen, secondLen := calcSplitAtLengths(len(slice), index)

first := make(AccountMetaSlice, firstLen)
copy(first, slice[:index])

second := make(AccountMetaSlice, secondLen)
copy(second, slice[index:])

return first, second
}

func calcSplitAtLengths(total int, index int) (int, int) {
if index == 0 {
return 0, total
}
if index > total-1 {
return total, 0
}
return index, total - index
}
61 changes: 61 additions & 0 deletions account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,3 +140,64 @@ func TestMeta(t *testing.T) {
require.True(t, meta.IsSigner)
require.True(t, meta.IsWritable)
}

func TestSplitFrom(t *testing.T) {
slice := make(AccountMetaSlice, 0)
slice = append(slice, Meta(BPFLoaderDeprecatedProgramID))
slice = append(slice, Meta(TokenProgramID))
slice = append(slice, Meta(TokenLendingProgramID))
slice = append(slice, Meta(SPLAssociatedTokenAccountProgramID))
slice = append(slice, Meta(MemoProgramID))

require.Len(t, slice, 5)

{
part1, part2 := slice.SplitFrom(0)
require.Len(t, part1, 0)
require.Len(t, part2, 5)
}
{
part1, part2 := slice.SplitFrom(1)
require.Len(t, part1, 1)
require.Len(t, part2, 4)
require.Equal(t, Meta(BPFLoaderDeprecatedProgramID), part1[0])
require.Equal(t, Meta(TokenProgramID), part2[0])
require.Equal(t, Meta(TokenLendingProgramID), part2[1])
require.Equal(t, Meta(SPLAssociatedTokenAccountProgramID), part2[2])
require.Equal(t, Meta(MemoProgramID), part2[3])
}
{
part1, part2 := slice.SplitFrom(2)
require.Len(t, part1, 2)
require.Len(t, part2, 3)
}
{
part1, part2 := slice.SplitFrom(3)
require.Len(t, part1, 3)
require.Len(t, part2, 2)
}
{
part1, part2 := slice.SplitFrom(4)
require.Len(t, part1, 4)
require.Len(t, part2, 1)
}
{
part1, part2 := slice.SplitFrom(5)
require.Len(t, part1, 5)
require.Len(t, part2, 0)
}
{
part1, part2 := slice.SplitFrom(6)
require.Len(t, part1, 5)
require.Len(t, part2, 0)
}
{
part1, part2 := slice.SplitFrom(10000)
require.Len(t, part1, 5)
require.Len(t, part2, 0)
}
require.Panics(t,
func() {
slice.SplitFrom(-1)
})
}
4 changes: 2 additions & 2 deletions cmd/slnc/cmd/token_get_mint.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,13 @@ var tokenGetMintCmd = &cobra.Command{
out = append(out, fmt.Sprintf("Supply | %d", mint.Supply))
out = append(out, fmt.Sprintf("Decimals | %d", mint.Decimals))

if mint.MintAuthorityOption != 0 {
if mint.MintAuthority != nil {
out = append(out, fmt.Sprintf("Token Authority | %s", mint.MintAuthority))
} else {
out = append(out, "No mint authority")
}

if mint.FreezeAuthorityOption != 0 {
if mint.FreezeAuthority != nil {
out = append(out, fmt.Sprintf("Freeze Authority | %s", mint.FreezeAuthority))
} else {
out = append(out, "No freeze authority")
Expand Down
5 changes: 2 additions & 3 deletions cmd/slnc/cmd/token_list_mints.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,15 @@ var tokenListMintsCmd = &cobra.Command{
out := []string{"Mint | Decimals | Supply | Token Authority | Freeze Authority"}
for _, m := range mints {
line := []string{
fmt.Sprintf("%d", m.MintAuthorityOption),
fmt.Sprintf("%d", m.Supply),
fmt.Sprintf("%d", m.Decimals),
}
if m.MintAuthorityOption != 0 {
if m.MintAuthority != nil {
line = append(line, fmt.Sprintf("%s", m.MintAuthority))
} else {
line = append(line, "No mint authority")
}
if m.FreezeAuthorityOption != 0 {
if m.FreezeAuthority != nil {
line = append(line, fmt.Sprintf("%s", m.FreezeAuthority))
} else {
line = append(line, "No freeze authority")
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ require (
github.com/fatih/color v1.7.0
github.com/gagliardetto/binary v0.4.1
github.com/gagliardetto/gofuzz v1.2.2
github.com/gagliardetto/treeout v0.1.2
github.com/gagliardetto/treeout v0.1.4
github.com/google/go-cmp v0.5.1
github.com/gorilla/rpc v1.2.0
github.com/gorilla/websocket v1.4.2
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ github.com/gagliardetto/binary v0.4.1 h1:3HXeBOfmR2HHIrF1YBnoqgFKQBtN8+rWA770KyX
github.com/gagliardetto/binary v0.4.1/go.mod h1:peJR9PvwamL4YOh1nHWCPLry2VEfeeD1ADvewka7HnQ=
github.com/gagliardetto/gofuzz v1.2.2 h1:XL/8qDMzcgvR4+CyRQW9UGdwPRPMHVJfqQ/uMvSUuQw=
github.com/gagliardetto/gofuzz v1.2.2/go.mod h1:bkH/3hYLZrMLbfYWA0pWzXmi5TTRZnu4pMGZBkqMKvY=
github.com/gagliardetto/treeout v0.1.2 h1:WXO7LDJTwINO37OQfNlf7s095Z1bAiwN2ACaZQic33Q=
github.com/gagliardetto/treeout v0.1.2/go.mod h1:loUefvXTrlRG5rYmJmExNryyBRh8f89VZhmMOyCyqok=
github.com/gagliardetto/treeout v0.1.4 h1:ozeYerrLCmCubo1TcIjFiOWTTGteOOHND1twdFpgwaw=
github.com/gagliardetto/treeout v0.1.4/go.mod h1:loUefvXTrlRG5rYmJmExNryyBRh8f89VZhmMOyCyqok=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
Expand Down
2 changes: 1 addition & 1 deletion keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ func findAssociatedTokenAddressAndBumpSeed(
) (PublicKey, uint8, error) {
return FindProgramAddress([][]byte{
walletAddress[:],
SPLTokenProgramID[:],
TokenProgramID[:],
splTokenMintAddress[:],
},
programID,
Expand Down
19 changes: 14 additions & 5 deletions program_ids.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@ var (
var (
// A Token program on the Solana blockchain.
// This program defines a common implementation for Fungible and Non Fungible tokens.
SPLTokenProgramID = MustPublicKeyFromBase58("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA")
TokenProgramID = MustPublicKeyFromBase58("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA")

// A Uniswap-like exchange for the Token program on the Solana blockchain,
// implementing multiple automated market maker (AMM) curves.
SPLTokenSwapProgramID = MustPublicKeyFromBase58("SwaPpA9LAaLfeLi3a68M4DjnLqgtticKg6CnyNwgAC8")
SPLTokenSwapFeeOwner = MustPublicKeyFromBase58("HfoTxFR1Tm6kGmWgYWD6J7YHVy1UwqSULUGVLXkJqaKN")
TokenSwapProgramID = MustPublicKeyFromBase58("SwaPpA9LAaLfeLi3a68M4DjnLqgtticKg6CnyNwgAC8")
TokenSwapFeeOwner = MustPublicKeyFromBase58("HfoTxFR1Tm6kGmWgYWD6J7YHVy1UwqSULUGVLXkJqaKN")

// A lending protocol for the Token program on the Solana blockchain inspired by Aave and Compound.
SPLTokenLendingProgramID = MustPublicKeyFromBase58("LendZqTs8gn5CTSJU1jWKhKuVpjJGom45nnwPb2AMTi")
TokenLendingProgramID = MustPublicKeyFromBase58("LendZqTs8gn5CTSJU1jWKhKuVpjJGom45nnwPb2AMTi")

// This program defines the convention and provides the mechanism for mapping
// the user's wallet address to the associated token accounts they hold.
Expand All @@ -49,5 +49,14 @@ var (
// to the transaction log, so that anyone can easily observe memos
// and know they were approved by zero or more addresses
// by inspecting the transaction log from a trusted provider.
SPLMemoProgramID = MustPublicKeyFromBase58("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr")
MemoProgramID = MustPublicKeyFromBase58("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr")
)

var (
// The Mint for native SOL Token accounts
SolMint = MustPublicKeyFromBase58("So11111111111111111111111111111111111111112")
)

var (
TokenMetadataProgramID = MustPublicKeyFromBase58("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s")
)
6 changes: 3 additions & 3 deletions programs/system/AdvanceNonceAccount.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,9 @@ func (inst *AdvanceNonceAccount) EncodeToTree(parent ag_treeout.Branches) {

// Accounts of the instruction:
instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) {
accountsBranch.Child(ag_format.Meta("NonceAccount", inst.AccountMetaSlice[0]))
accountsBranch.Child(ag_format.Meta("$(SysVarRecentBlockHashesPubkey)", inst.AccountMetaSlice[1]))
accountsBranch.Child(ag_format.Meta("NonceAuthorityAccount", inst.AccountMetaSlice[2]))
accountsBranch.Child(ag_format.Meta(" Nonce", inst.AccountMetaSlice[0]))
accountsBranch.Child(ag_format.Meta("SysVarRecentBlockHashes", inst.AccountMetaSlice[1]))
accountsBranch.Child(ag_format.Meta(" NonceAuthority", inst.AccountMetaSlice[2]))
})
})
})
Expand Down
2 changes: 1 addition & 1 deletion programs/system/Allocate.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func (inst *Allocate) EncodeToTree(parent ag_treeout.Branches) {

// Accounts of the instruction:
instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) {
accountsBranch.Child(ag_format.Meta("NewAccount", inst.AccountMetaSlice[0]))
accountsBranch.Child(ag_format.Meta("New", inst.AccountMetaSlice[0]))
})
})
})
Expand Down
8 changes: 4 additions & 4 deletions programs/system/AllocateWithSeed.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,16 +138,16 @@ func (inst *AllocateWithSeed) EncodeToTree(parent ag_treeout.Branches) {

// Parameters of the instruction:
instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) {
paramsBranch.Child(ag_format.Param("Base", *inst.Base))
paramsBranch.Child(ag_format.Param("Seed", *inst.Seed))
paramsBranch.Child(ag_format.Param(" Base", *inst.Base))
paramsBranch.Child(ag_format.Param(" Seed", *inst.Seed))
paramsBranch.Child(ag_format.Param("Space", *inst.Space))
paramsBranch.Child(ag_format.Param("Owner", *inst.Owner))
})

// Accounts of the instruction:
instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) {
accountsBranch.Child(ag_format.Meta("AllocatedAccount", inst.AccountMetaSlice[0]))
accountsBranch.Child(ag_format.Meta("BaseAccount", inst.AccountMetaSlice[1]))
accountsBranch.Child(ag_format.Meta("Allocated", inst.AccountMetaSlice[0]))
accountsBranch.Child(ag_format.Meta(" Base", inst.AccountMetaSlice[1]))
})
})
})
Expand Down
2 changes: 1 addition & 1 deletion programs/system/Assign.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func (inst *Assign) EncodeToTree(parent ag_treeout.Branches) {

// Accounts of the instruction:
instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) {
accountsBranch.Child(ag_format.Meta("AssignedAccount", inst.AccountMetaSlice[0]))
accountsBranch.Child(ag_format.Meta("Assigned", inst.AccountMetaSlice[0]))
})
})
})
Expand Down
8 changes: 4 additions & 4 deletions programs/system/AssignWithSeed.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,15 +126,15 @@ func (inst *AssignWithSeed) EncodeToTree(parent ag_treeout.Branches) {

// Parameters of the instruction:
instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) {
paramsBranch.Child(ag_format.Param("Base", *inst.Base))
paramsBranch.Child(ag_format.Param("Seed", *inst.Seed))
paramsBranch.Child(ag_format.Param(" Base", *inst.Base))
paramsBranch.Child(ag_format.Param(" Seed", *inst.Seed))
paramsBranch.Child(ag_format.Param("Owner", *inst.Owner))
})

// Accounts of the instruction:
instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) {
accountsBranch.Child(ag_format.Meta("AssignedAccount", inst.AccountMetaSlice[0]))
accountsBranch.Child(ag_format.Meta("BaseAccount", inst.AccountMetaSlice[1]))
accountsBranch.Child(ag_format.Meta("Assigned", inst.AccountMetaSlice[0]))
accountsBranch.Child(ag_format.Meta(" Base", inst.AccountMetaSlice[1]))
})
})
})
Expand Down
4 changes: 2 additions & 2 deletions programs/system/AuthorizeNonceAccount.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,8 @@ func (inst *AuthorizeNonceAccount) EncodeToTree(parent ag_treeout.Branches) {

// Accounts of the instruction:
instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) {
accountsBranch.Child(ag_format.Meta("NonceAccount", inst.AccountMetaSlice[0]))
accountsBranch.Child(ag_format.Meta("NonceAuthorityAccount", inst.AccountMetaSlice[1]))
accountsBranch.Child(ag_format.Meta(" Nonce", inst.AccountMetaSlice[0]))
accountsBranch.Child(ag_format.Meta("NonceAuthority", inst.AccountMetaSlice[1]))
})
})
})
Expand Down
8 changes: 4 additions & 4 deletions programs/system/CreateAccount.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,14 +127,14 @@ func (inst *CreateAccount) EncodeToTree(parent ag_treeout.Branches) {
// Parameters of the instruction:
instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) {
paramsBranch.Child(ag_format.Param("Lamports", *inst.Lamports))
paramsBranch.Child(ag_format.Param("Space", *inst.Space))
paramsBranch.Child(ag_format.Param("Owner", *inst.Owner))
paramsBranch.Child(ag_format.Param(" Space", *inst.Space))
paramsBranch.Child(ag_format.Param(" Owner", *inst.Owner))
})

// Accounts of the instruction:
instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) {
accountsBranch.Child(ag_format.Meta("FundingAccount", inst.AccountMetaSlice[0]))
accountsBranch.Child(ag_format.Meta("NewAccount", inst.AccountMetaSlice[1]))
accountsBranch.Child(ag_format.Meta("Funding", inst.AccountMetaSlice[0]))
accountsBranch.Child(ag_format.Meta(" New", inst.AccountMetaSlice[1]))
})
})
})
Expand Down
14 changes: 7 additions & 7 deletions programs/system/CreateAccountWithSeed.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,18 +171,18 @@ func (inst *CreateAccountWithSeed) EncodeToTree(parent ag_treeout.Branches) {

// Parameters of the instruction:
instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) {
paramsBranch.Child(ag_format.Param("Base", *inst.Base))
paramsBranch.Child(ag_format.Param("Seed", *inst.Seed))
paramsBranch.Child(ag_format.Param(" Base", *inst.Base))
paramsBranch.Child(ag_format.Param(" Seed", *inst.Seed))
paramsBranch.Child(ag_format.Param("Lamports", *inst.Lamports))
paramsBranch.Child(ag_format.Param("Space", *inst.Space))
paramsBranch.Child(ag_format.Param("Owner", *inst.Owner))
paramsBranch.Child(ag_format.Param(" Space", *inst.Space))
paramsBranch.Child(ag_format.Param(" Owner", *inst.Owner))
})

// Accounts of the instruction:
instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) {
accountsBranch.Child(ag_format.Meta("FundingAccount", inst.AccountMetaSlice[0]))
accountsBranch.Child(ag_format.Meta("CreatedAccount", inst.AccountMetaSlice[1]))
accountsBranch.Child(ag_format.Meta("BaseAccount", inst.AccountMetaSlice[2]))
accountsBranch.Child(ag_format.Meta("Funding", inst.AccountMetaSlice[0]))
accountsBranch.Child(ag_format.Meta("Created", inst.AccountMetaSlice[1]))
accountsBranch.Child(ag_format.Meta(" Base", inst.AccountMetaSlice[2]))
})
})
})
Expand Down
6 changes: 3 additions & 3 deletions programs/system/InitializeNonceAccount.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,9 @@ func (inst *InitializeNonceAccount) EncodeToTree(parent ag_treeout.Branches) {

// Accounts of the instruction:
instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) {
accountsBranch.Child(ag_format.Meta("NonceAccount", inst.AccountMetaSlice[0]))
accountsBranch.Child(ag_format.Meta("$(SysVarRecentBlockHashesPubkey)", inst.AccountMetaSlice[1]))
accountsBranch.Child(ag_format.Meta("$(SysVarRentPubkey)", inst.AccountMetaSlice[2]))
accountsBranch.Child(ag_format.Meta(" Nonce", inst.AccountMetaSlice[0]))
accountsBranch.Child(ag_format.Meta("SysVarRecentBlockHashes", inst.AccountMetaSlice[1]))
accountsBranch.Child(ag_format.Meta(" SysVarRent", inst.AccountMetaSlice[2]))
})
})
})
Expand Down
4 changes: 2 additions & 2 deletions programs/system/Transfer.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,8 @@ func (inst *Transfer) EncodeToTree(parent ag_treeout.Branches) {

// Accounts of the instruction:
instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) {
accountsBranch.Child(ag_format.Meta("FundingAccount", inst.AccountMetaSlice[0]))
accountsBranch.Child(ag_format.Meta("RecipientAccount", inst.AccountMetaSlice[1]))
accountsBranch.Child(ag_format.Meta(" Funding", inst.AccountMetaSlice[0]))
accountsBranch.Child(ag_format.Meta("Recipient", inst.AccountMetaSlice[1]))
})
})
})
Expand Down
Loading

0 comments on commit be93bc0

Please sign in to comment.