Skip to content

Commit c5cdda0

Browse files
committed
Implement Go interface to currency creator Solana program (WIP)
1 parent f3cb649 commit c5cdda0

18 files changed

+1161
-153
lines changed
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package currencycreator
2+
3+
import (
4+
"bytes"
5+
"crypto/ed25519"
6+
"fmt"
7+
8+
"github.com/mr-tron/base58"
9+
)
10+
11+
const (
12+
DefaultMintMaxSupply = 21_000_000_000_000
13+
DefaultMintDecimals = 6
14+
)
15+
16+
const (
17+
MaxCurrencyConfigAccountNameLength = 32
18+
MaxCurrencyConfigAccountSymbolLength = 8
19+
)
20+
21+
const (
22+
CurrencyConfigAccountSize = (8 + //discriminator
23+
32 + // authority
24+
32 + // creator
25+
32 + // mint
26+
MaxCurrencyConfigAccountNameLength + // name
27+
MaxCurrencyConfigAccountSymbolLength + // symbol
28+
32 + // seed
29+
8 + // max_supply
30+
8 + // current_supply
31+
1 + // decimal_places
32+
1 + // bump
33+
1 + // mint_bump
34+
5) // padding
35+
)
36+
37+
var CurrencyConfigAccountDiscriminator = []byte{byte(AccountTypeCurrencyConfig), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
38+
39+
type CurrencyConfigAccount struct {
40+
Authority ed25519.PublicKey
41+
Creator ed25519.PublicKey
42+
Mint ed25519.PublicKey
43+
Name string
44+
Symbol string
45+
Seed ed25519.PublicKey
46+
MaxSupply uint64
47+
CurrentSupply uint64
48+
DecimalPlaces uint8
49+
Bump uint8
50+
MintBump uint8
51+
}
52+
53+
func (obj *CurrencyConfigAccount) Unmarshal(data []byte) error {
54+
if len(data) < CurrencyConfigAccountSize {
55+
return ErrInvalidAccountData
56+
}
57+
58+
var offset int
59+
60+
var discriminator []byte
61+
getDiscriminator(data, &discriminator, &offset)
62+
if !bytes.Equal(discriminator, CurrencyConfigAccountDiscriminator) {
63+
return ErrInvalidAccountData
64+
}
65+
66+
getKey(data, &obj.Authority, &offset)
67+
getKey(data, &obj.Creator, &offset)
68+
getKey(data, &obj.Mint, &offset)
69+
getFixedString(data, &obj.Name, MaxCurrencyConfigAccountNameLength, &offset)
70+
getFixedString(data, &obj.Symbol, MaxCurrencyConfigAccountSymbolLength, &offset)
71+
getKey(data, &obj.Seed, &offset)
72+
getUint64(data, &obj.MaxSupply, &offset)
73+
getUint64(data, &obj.CurrentSupply, &offset)
74+
getUint8(data, &obj.DecimalPlaces, &offset)
75+
getUint8(data, &obj.Bump, &offset)
76+
getUint8(data, &obj.MintBump, &offset)
77+
offset += 5 // padding
78+
79+
return nil
80+
}
81+
82+
func (obj *CurrencyConfigAccount) String() string {
83+
return fmt.Sprintf(
84+
"CurrencyConfig{authority=%s,creator=%s,mint=%s,name=%s,symbol=%s,seed=%s,max_supply=%d,currency_supply=%d,decimal_places=%d,bump=%d,mint_bump=%d}",
85+
base58.Encode(obj.Authority),
86+
base58.Encode(obj.Creator),
87+
base58.Encode(obj.Mint),
88+
obj.Name,
89+
obj.Symbol,
90+
base58.Encode(obj.Seed),
91+
obj.MaxSupply,
92+
obj.CurrentSupply,
93+
obj.DecimalPlaces,
94+
obj.Bump,
95+
obj.MintBump,
96+
)
97+
}
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
package currencycreator
2+
3+
import (
4+
"bytes"
5+
"crypto/ed25519"
6+
"fmt"
7+
"time"
8+
9+
"github.com/mr-tron/base58"
10+
)
11+
12+
const (
13+
LiquidityPoolAccountSize = (8 + //discriminator
14+
32 + // authority
15+
32 + // currency
16+
32 + // target_mint
17+
32 + // base_mint
18+
32 + // vault_target
19+
32 + // vault_base
20+
32 + // fee_target
21+
32 + // fee_base
22+
4 + // buy_fee
23+
4 + // sell_fee
24+
8 + // created_unix_time
25+
8 + // go_live_unix_time
26+
8 + // purchase_cap
27+
8 + // sale_cap
28+
RawExponentialCurveSize + // curve
29+
8 + // supply_from_baseonding
30+
1 + // bump
31+
1 + // currency_baseump
32+
1 + // vault_target_baseump
33+
1 + // vault_base_baseump
34+
4) // padding
35+
)
36+
37+
var LiquidityPoolAccountDiscriminator = []byte{byte(AccountTypeLiquidityPool), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
38+
39+
type LiquidityPoolAccount struct {
40+
Authority ed25519.PublicKey
41+
Currency ed25519.PublicKey
42+
TargetMint ed25519.PublicKey
43+
BaseMint ed25519.PublicKey
44+
VaultTarget ed25519.PublicKey
45+
VaultBase ed25519.PublicKey
46+
FeeTarget ed25519.PublicKey
47+
FeeBase ed25519.PublicKey
48+
BuyFee uint32
49+
SellFee uint32
50+
CreatedUnixTime int64
51+
GoLiveUnixTime int64
52+
PurchaseCap uint64
53+
SaleCap uint64
54+
Curve RawExponentialCurve
55+
SupplyFromBonding uint64
56+
Bump uint8
57+
CurrencyBump uint8
58+
VaultTargetBump uint8
59+
VaultBaseBump uint8
60+
}
61+
62+
func (obj *LiquidityPoolAccount) Unmarshal(data []byte) error {
63+
if len(data) < LiquidityPoolAccountSize {
64+
return ErrInvalidAccountData
65+
}
66+
67+
var offset int
68+
69+
var discriminator []byte
70+
getDiscriminator(data, &discriminator, &offset)
71+
if !bytes.Equal(discriminator, LiquidityPoolAccountDiscriminator) {
72+
return ErrInvalidAccountData
73+
}
74+
75+
getKey(data, &obj.Authority, &offset)
76+
getKey(data, &obj.Currency, &offset)
77+
getKey(data, &obj.TargetMint, &offset)
78+
getKey(data, &obj.BaseMint, &offset)
79+
getKey(data, &obj.VaultTarget, &offset)
80+
getKey(data, &obj.VaultBase, &offset)
81+
getKey(data, &obj.FeeTarget, &offset)
82+
getKey(data, &obj.FeeBase, &offset)
83+
getUint32(data, &obj.BuyFee, &offset)
84+
getUint32(data, &obj.SellFee, &offset)
85+
getInt64(data, &obj.CreatedUnixTime, &offset)
86+
getInt64(data, &obj.GoLiveUnixTime, &offset)
87+
getUint64(data, &obj.PurchaseCap, &offset)
88+
getUint64(data, &obj.SaleCap, &offset)
89+
getRawExponentialCurve(data, &obj.Curve, &offset)
90+
getUint64(data, &obj.SupplyFromBonding, &offset)
91+
getUint8(data, &obj.Bump, &offset)
92+
getUint8(data, &obj.CurrencyBump, &offset)
93+
getUint8(data, &obj.VaultTargetBump, &offset)
94+
getUint8(data, &obj.VaultBaseBump, &offset)
95+
offset += 4 // padding
96+
97+
return nil
98+
}
99+
100+
func (obj *LiquidityPoolAccount) String() string {
101+
return fmt.Sprintf(
102+
"LiquidityPool{authority=%s,currency=%s,target_mint=%s,base_mint=%s,vault_target=%s,vault_base=%s,fee_target=%s,fee_base=%s,buy_fee=%d,sell_fee=%d,created_unix_time=%s,go_live_unix_time=%s,purchase_cap=%d,sale_cap=%d,curve=%s,bump=%d,currency_bump=%d,vault_target_bump=%d,vault_base_bump=%d}",
103+
base58.Encode(obj.Authority),
104+
base58.Encode(obj.Currency),
105+
base58.Encode(obj.TargetMint),
106+
base58.Encode(obj.BaseMint),
107+
base58.Encode(obj.VaultTarget),
108+
base58.Encode(obj.VaultBase),
109+
base58.Encode(obj.FeeTarget),
110+
base58.Encode(obj.FeeBase),
111+
obj.BuyFee,
112+
obj.SellFee,
113+
time.Unix(obj.CreatedUnixTime, 0).UTC().String(),
114+
time.Unix(obj.GoLiveUnixTime, 0).UTC().String(),
115+
obj.PurchaseCap,
116+
obj.SaleCap,
117+
obj.Curve.String(),
118+
obj.Bump,
119+
obj.CurrencyBump,
120+
obj.VaultTargetBump,
121+
obj.VaultBaseBump,
122+
)
123+
}

pkg/solana/currencycreator/address.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package currencycreator
2+
3+
import (
4+
"crypto/ed25519"
5+
6+
"github.com/code-payments/code-server/pkg/solana"
7+
)
8+
9+
var (
10+
MintPrefix = []byte("mint")
11+
CurrencyPrefix = []byte("currency")
12+
PoolPrefix = []byte("pool")
13+
TreasuryPrefix = []byte("treasury")
14+
MetadataPrefix = []byte("metadata")
15+
)
16+
17+
type GetMintAddressArgs struct {
18+
Authority ed25519.PublicKey
19+
Name string
20+
Seed ed25519.PublicKey
21+
}
22+
23+
func GetMintAddress(args *GetMintAddressArgs) (ed25519.PublicKey, uint8, error) {
24+
return solana.FindProgramAddressAndBump(
25+
PROGRAM_ID,
26+
MintPrefix,
27+
args.Authority,
28+
[]byte(toFixedString(args.Name, MaxCurrencyConfigAccountNameLength)),
29+
args.Seed,
30+
)
31+
}
32+
33+
type GetCurrencyAddressArgs struct {
34+
Mint ed25519.PublicKey
35+
}
36+
37+
func GetCurrencyAddress(args *GetCurrencyAddressArgs) (ed25519.PublicKey, uint8, error) {
38+
return solana.FindProgramAddressAndBump(
39+
PROGRAM_ID,
40+
CurrencyPrefix,
41+
args.Mint,
42+
)
43+
}
44+
45+
type GetPoolAddressArgs struct {
46+
Currency ed25519.PublicKey
47+
}
48+
49+
func GetPoolAddress(args *GetPoolAddressArgs) (ed25519.PublicKey, uint8, error) {
50+
return solana.FindProgramAddressAndBump(
51+
PROGRAM_ID,
52+
PoolPrefix,
53+
args.Currency,
54+
)
55+
}
56+
57+
type GetVaultAddressArgs struct {
58+
Pool ed25519.PublicKey
59+
Mint ed25519.PublicKey
60+
}
61+
62+
func GetVaultAddress(args *GetVaultAddressArgs) (ed25519.PublicKey, uint8, error) {
63+
return solana.FindProgramAddressAndBump(
64+
PROGRAM_ID,
65+
TreasuryPrefix,
66+
args.Pool,
67+
args.Mint,
68+
)
69+
}
70+
71+
type GetMetadataAddressArgs struct {
72+
Mint ed25519.PublicKey
73+
}
74+
75+
func GetMetadataAddress(args *GetMetadataAddressArgs) (ed25519.PublicKey, uint8, error) {
76+
return solana.FindProgramAddressAndBump(
77+
METADATA_PROGRAM_ID,
78+
MetadataPrefix,
79+
METADATA_PROGRAM_ID,
80+
args.Mint,
81+
)
82+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package currencycreator
2+
3+
import (
4+
"math"
5+
"math/big"
6+
)
7+
8+
func EstimateCurrentPrice(
9+
curve *ExponentialCurve,
10+
currentSupplyInQuarks uint64,
11+
decimals uint8,
12+
) *big.Float {
13+
scale := big.NewFloat(math.Pow10(int(decimals))).SetPrec(defaultExponentialCurvePrec)
14+
unscaledCurrentSupply := big.NewFloat(float64(currentSupplyInQuarks)).SetPrec(defaultExponentialCurvePrec)
15+
scaledCurrentSupply := new(big.Float).Quo(unscaledCurrentSupply, scale)
16+
return curve.SpotPriceAtSupply(scaledCurrentSupply)
17+
}
18+
19+
func EstimateBuy(
20+
curve *ExponentialCurve,
21+
buyAmountInQuarks,
22+
currentSupplyInQuarks uint64,
23+
buyFee uint32,
24+
targetMintDecimals,
25+
baseMintDecimals uint8,
26+
) (uint64, uint64) {
27+
scale := big.NewFloat(math.Pow10(int(baseMintDecimals))).SetPrec(defaultExponentialCurvePrec)
28+
unscaledBuyAmount := big.NewFloat(float64(buyAmountInQuarks)).SetPrec(defaultExponentialCurvePrec)
29+
scaledBuyAmount := new(big.Float).Quo(unscaledBuyAmount, scale)
30+
31+
scale = big.NewFloat(math.Pow10(int(targetMintDecimals))).SetPrec(defaultExponentialCurvePrec)
32+
unscaledCurrentSupply := big.NewFloat(float64(currentSupplyInQuarks)).SetPrec(defaultExponentialCurvePrec)
33+
scaledCurrentSupply := new(big.Float).Quo(unscaledCurrentSupply, scale)
34+
35+
scale = big.NewFloat(math.Pow10(int(targetMintDecimals))).SetPrec(defaultExponentialCurvePrec)
36+
scaledTotalValue := curve.ValueToTokens(scaledCurrentSupply, scaledBuyAmount)
37+
unscaledTotalValue := new(big.Float).Mul(scaledTotalValue, scale)
38+
total, _ := unscaledTotalValue.Int64()
39+
40+
feePctValue := new(big.Float).SetPrec(defaultExponentialCurvePrec).Quo(big.NewFloat(float64(buyFee)), big.NewFloat(10000))
41+
scaledFees := new(big.Float).Mul(scaledTotalValue, feePctValue)
42+
unscaledFees := new(big.Float).Mul(scaledFees, scale)
43+
fees, _ := unscaledFees.Int64()
44+
45+
return uint64(total - fees), uint64(fees)
46+
}
47+
48+
func EstimateSale(
49+
curve *ExponentialCurve,
50+
sellAmountInQuarks,
51+
currentSupplyInQuarks uint64,
52+
sellFee uint32,
53+
targetMintDecimals,
54+
baseMintDecimals uint8,
55+
) (uint64, uint64) {
56+
scale := big.NewFloat(math.Pow10(int(targetMintDecimals))).SetPrec(defaultExponentialCurvePrec)
57+
unscaledSellAmount := big.NewFloat(float64(sellAmountInQuarks)).SetPrec(defaultExponentialCurvePrec)
58+
scaledSellAmount := new(big.Float).Quo(unscaledSellAmount, scale)
59+
60+
scale = big.NewFloat(math.Pow10(int(targetMintDecimals))).SetPrec(defaultExponentialCurvePrec)
61+
unscaledCurrentSupply := big.NewFloat(float64(currentSupplyInQuarks)).SetPrec(defaultExponentialCurvePrec)
62+
scaledCurrentSupply := new(big.Float).Quo(unscaledCurrentSupply, scale)
63+
64+
scale = big.NewFloat(math.Pow10(int(baseMintDecimals))).SetPrec(defaultExponentialCurvePrec)
65+
scaledTotalValue := curve.TokensToValue(scaledCurrentSupply, scaledSellAmount)
66+
unscaledTotalValue := new(big.Float).Mul(scaledTotalValue, scale)
67+
total, _ := unscaledTotalValue.Int64()
68+
69+
feePctValue := new(big.Float).SetPrec(defaultExponentialCurvePrec).Quo(big.NewFloat(float64(sellFee)), big.NewFloat(10000))
70+
scaledFees := new(big.Float).Mul(scaledTotalValue, feePctValue)
71+
unscaledFees := new(big.Float).Mul(scaledFees, scale)
72+
fees, _ := unscaledFees.Int64()
73+
74+
return uint64(total - fees), uint64(fees)
75+
}

0 commit comments

Comments
 (0)