2020-11-09 10:09:50 -08:00
|
|
|
// Copyright 2020 dfuse Platform Inc.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2020-08-14 15:29:24 -07:00
|
|
|
package system
|
|
|
|
|
|
|
|
import (
|
2020-11-24 11:39:33 -08:00
|
|
|
"bytes"
|
2020-11-26 09:51:11 -08:00
|
|
|
"encoding/binary"
|
2020-11-18 05:39:50 -08:00
|
|
|
"fmt"
|
|
|
|
|
2020-11-12 14:57:43 -08:00
|
|
|
bin "github.com/dfuse-io/binary"
|
2021-07-06 09:18:26 -07:00
|
|
|
solana "github.com/gagliardetto/solana-go"
|
|
|
|
"github.com/gagliardetto/solana-go/text"
|
2020-08-14 15:29:24 -07:00
|
|
|
)
|
|
|
|
|
2020-11-18 13:45:59 -08:00
|
|
|
var PROGRAM_ID = solana.MustPublicKeyFromBase58("11111111111111111111111111111111")
|
2020-11-18 05:39:50 -08:00
|
|
|
|
|
|
|
func init() {
|
2020-11-18 13:45:59 -08:00
|
|
|
solana.RegisterInstructionDecoder(PROGRAM_ID, registryDecodeInstruction)
|
2020-11-18 05:39:50 -08:00
|
|
|
}
|
|
|
|
|
2021-01-20 10:18:07 -08:00
|
|
|
func registryDecodeInstruction(accounts []*solana.AccountMeta, data []byte) (interface{}, error) {
|
|
|
|
inst, err := DecodeInstruction(accounts, data)
|
2020-11-18 05:39:50 -08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return inst, nil
|
|
|
|
}
|
|
|
|
|
2021-01-20 10:18:07 -08:00
|
|
|
func DecodeInstruction(accounts []*solana.AccountMeta, data []byte) (*Instruction, error) {
|
2020-11-18 13:45:59 -08:00
|
|
|
var inst *Instruction
|
2021-01-20 10:18:07 -08:00
|
|
|
if err := bin.NewDecoder(data).Decode(&inst); err != nil {
|
2020-11-18 05:39:50 -08:00
|
|
|
return nil, fmt.Errorf("unable to decode instruction for serum program: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if v, ok := inst.Impl.(solana.AccountSettable); ok {
|
2021-01-20 10:18:07 -08:00
|
|
|
err := v.SetAccounts(accounts)
|
2020-11-18 13:53:31 -08:00
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("unable to set accounts for instruction: %w", err)
|
|
|
|
}
|
2020-11-18 05:39:50 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
return inst, nil
|
|
|
|
}
|
|
|
|
|
2020-11-26 14:05:05 -08:00
|
|
|
func NewCreateAccountInstruction(lamports uint64, space uint64, owner, from, to solana.PublicKey) *Instruction {
|
|
|
|
return &Instruction{
|
|
|
|
BaseVariant: bin.BaseVariant{
|
|
|
|
TypeID: 0,
|
|
|
|
Impl: &CreateAccount{
|
|
|
|
Lamports: bin.Uint64(lamports),
|
|
|
|
Space: bin.Uint64(space),
|
|
|
|
Owner: owner,
|
|
|
|
Accounts: &CreateAccountAccounts{
|
|
|
|
From: &solana.AccountMeta{PublicKey: from, IsSigner: true, IsWritable: true},
|
2020-11-27 04:44:56 -08:00
|
|
|
New: &solana.AccountMeta{PublicKey: to, IsSigner: true, IsWritable: true},
|
2020-11-26 14:05:05 -08:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-18 13:45:59 -08:00
|
|
|
type Instruction struct {
|
2020-11-12 14:57:43 -08:00
|
|
|
bin.BaseVariant
|
2020-08-14 15:29:24 -07:00
|
|
|
}
|
|
|
|
|
2020-11-26 14:05:05 -08:00
|
|
|
func (i *Instruction) Accounts() (out []*solana.AccountMeta) {
|
|
|
|
switch i.TypeID {
|
|
|
|
case 0:
|
|
|
|
accounts := i.Impl.(*CreateAccount).Accounts
|
|
|
|
out = []*solana.AccountMeta{accounts.From, accounts.New}
|
|
|
|
case 1:
|
|
|
|
// no account here
|
|
|
|
case 2:
|
|
|
|
accounts := i.Impl.(*Transfer).Accounts
|
|
|
|
out = []*solana.AccountMeta{accounts.From, accounts.To}
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (i *Instruction) ProgramID() solana.PublicKey {
|
|
|
|
return PROGRAM_ID
|
|
|
|
}
|
|
|
|
|
|
|
|
func (i *Instruction) Data() ([]byte, error) {
|
|
|
|
buf := new(bytes.Buffer)
|
|
|
|
if err := bin.NewEncoder(buf).Encode(i); err != nil {
|
|
|
|
return nil, fmt.Errorf("unable to encode instruction: %w", err)
|
|
|
|
}
|
|
|
|
return buf.Bytes(), nil
|
|
|
|
}
|
|
|
|
|
2020-11-20 11:24:07 -08:00
|
|
|
func (i *Instruction) TextEncode(encoder *text.Encoder, option *text.Option) error {
|
|
|
|
return encoder.Encode(i.Impl, option)
|
2020-11-18 13:45:59 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
var InstructionImplDef = bin.NewVariantDefinition(bin.Uint32TypeIDEncoding, []bin.VariantType{
|
2020-11-12 14:57:43 -08:00
|
|
|
{"create_account", (*CreateAccount)(nil)},
|
|
|
|
{"assign", (*Assign)(nil)},
|
|
|
|
{"transfer", (*Transfer)(nil)},
|
|
|
|
})
|
2020-11-06 11:43:44 -08:00
|
|
|
|
2020-11-18 13:45:59 -08:00
|
|
|
func (i *Instruction) UnmarshalBinary(decoder *bin.Decoder) error {
|
|
|
|
return i.BaseVariant.UnmarshalBinaryVariant(decoder, InstructionImplDef)
|
2020-11-09 07:02:28 -08:00
|
|
|
}
|
2020-11-06 11:43:44 -08:00
|
|
|
|
2020-11-26 09:51:11 -08:00
|
|
|
func (i *Instruction) MarshalBinary(encoder *bin.Encoder) error {
|
|
|
|
err := encoder.WriteUint32(i.TypeID, binary.LittleEndian)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("unable to write variant type: %w", err)
|
|
|
|
}
|
|
|
|
return encoder.Encode(i.Impl)
|
|
|
|
}
|
|
|
|
|
2020-11-20 11:24:07 -08:00
|
|
|
type CreateAccountAccounts struct {
|
|
|
|
From *solana.AccountMeta `text:"linear,notype"`
|
|
|
|
New *solana.AccountMeta `text:"linear,notype"`
|
|
|
|
}
|
|
|
|
|
2020-08-14 15:29:24 -07:00
|
|
|
type CreateAccount struct {
|
2020-11-12 14:57:43 -08:00
|
|
|
Lamports bin.Uint64
|
|
|
|
Space bin.Uint64
|
2020-08-14 15:29:24 -07:00
|
|
|
Owner solana.PublicKey
|
2020-11-20 11:24:07 -08:00
|
|
|
Accounts *CreateAccountAccounts `bin:"-"`
|
2020-08-14 15:29:24 -07:00
|
|
|
}
|
|
|
|
|
2021-01-20 10:18:07 -08:00
|
|
|
func (i *CreateAccount) SetAccounts(accounts []*solana.AccountMeta) error {
|
2020-11-20 11:24:07 -08:00
|
|
|
i.Accounts = &CreateAccountAccounts{
|
2021-01-20 10:18:07 -08:00
|
|
|
From: accounts[0],
|
|
|
|
New: accounts[1],
|
2020-11-20 11:24:07 -08:00
|
|
|
}
|
|
|
|
return nil
|
2020-11-18 13:45:59 -08:00
|
|
|
}
|
|
|
|
|
2020-08-14 15:29:24 -07:00
|
|
|
type Assign struct {
|
|
|
|
// prefixed with byte 0x01
|
|
|
|
Owner solana.PublicKey
|
|
|
|
}
|
|
|
|
|
|
|
|
type Transfer struct {
|
|
|
|
// Prefixed with byte 0x02
|
2020-11-12 14:57:43 -08:00
|
|
|
Lamports bin.Uint64
|
2020-11-20 11:24:07 -08:00
|
|
|
Accounts *TransferAccounts `bin:"-"`
|
2020-08-14 15:29:24 -07:00
|
|
|
}
|
|
|
|
|
2020-11-20 11:24:07 -08:00
|
|
|
type TransferAccounts struct {
|
|
|
|
From *solana.AccountMeta `text:"linear,notype"`
|
|
|
|
To *solana.AccountMeta `text:"linear,notype"`
|
|
|
|
}
|
|
|
|
|
2021-01-22 04:48:34 -08:00
|
|
|
func (i *Transfer) SetAccounts(accounts []*solana.AccountMeta) error {
|
2020-11-20 11:24:07 -08:00
|
|
|
i.Accounts = &TransferAccounts{
|
2021-01-22 04:48:34 -08:00
|
|
|
From: accounts[0],
|
|
|
|
To: accounts[1],
|
2020-11-20 11:24:07 -08:00
|
|
|
}
|
|
|
|
return nil
|
2020-11-18 13:45:59 -08:00
|
|
|
}
|
|
|
|
|
2020-08-14 15:29:24 -07:00
|
|
|
type CreateAccountWithSeed struct {
|
|
|
|
// Prefixed with byte 0x03
|
|
|
|
Base solana.PublicKey
|
2020-11-13 06:21:00 -08:00
|
|
|
SeedSize int `bin:"sizeof=Seed"`
|
2020-08-14 15:29:24 -07:00
|
|
|
Seed string
|
2020-11-12 14:57:43 -08:00
|
|
|
Lamports bin.Uint64
|
|
|
|
Space bin.Uint64
|
2020-08-14 15:29:24 -07:00
|
|
|
Owner solana.PublicKey
|
|
|
|
}
|
|
|
|
|
|
|
|
type AdvanceNonceAccount struct {
|
|
|
|
// Prefix with 0x04
|
|
|
|
}
|
|
|
|
|
|
|
|
type WithdrawNonceAccount struct {
|
|
|
|
// Prefix with 0x05
|
2020-11-12 14:57:43 -08:00
|
|
|
Lamports bin.Uint64
|
2020-08-14 15:29:24 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
type InitializeNonceAccount struct {
|
|
|
|
// Prefix with 0x06
|
|
|
|
AuthorizedAccount solana.PublicKey
|
|
|
|
}
|
|
|
|
|
|
|
|
type AuthorizeNonceAccount struct {
|
|
|
|
// Prefix with 0x07
|
|
|
|
AuthorizeAccount solana.PublicKey
|
|
|
|
}
|
|
|
|
|
|
|
|
type Allocate struct {
|
|
|
|
// Prefix with 0x08
|
2020-11-12 14:57:43 -08:00
|
|
|
Space bin.Uint64
|
2020-08-14 15:29:24 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
type AllocateWithSeed struct {
|
|
|
|
// Prefixed with byte 0x09
|
|
|
|
Base solana.PublicKey
|
2020-11-13 06:21:00 -08:00
|
|
|
SeedSize int `bin:"sizeof=Seed"`
|
2020-08-14 15:29:24 -07:00
|
|
|
Seed string
|
2020-11-12 14:57:43 -08:00
|
|
|
Space bin.Uint64
|
2020-08-14 15:29:24 -07:00
|
|
|
Owner solana.PublicKey
|
|
|
|
}
|
|
|
|
|
|
|
|
type AssignWithSeed struct {
|
|
|
|
// Prefixed with byte 0x0a
|
|
|
|
Base solana.PublicKey
|
2020-11-13 06:21:00 -08:00
|
|
|
SeedSize int `bin:"sizeof=Seed"`
|
2020-08-14 15:29:24 -07:00
|
|
|
Seed string
|
|
|
|
Owner solana.PublicKey
|
|
|
|
}
|