Skip to content

Commit

Permalink
deserialize tokenswap (#266)
Browse files Browse the repository at this point in the history
  • Loading branch information
thesoftwarejedi authored Dec 7, 2021
1 parent 8369ac1 commit 966b71b
Show file tree
Hide file tree
Showing 8 changed files with 291 additions and 64 deletions.
27 changes: 20 additions & 7 deletions src/Solnet.Examples/TokenSwapExample.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ public class TokenSwapExample : IExample

public void Run()
{
//how to load current state
IRpcClient mainnetRpc = ClientFactory.GetClient(Cluster.MainNet);
var resp = mainnetRpc.GetAccountInfo("GAM8dQkm4LwYJgPZbML61mKPUCQX7uAquxu67p9oifSK");
var obj = TokenSwapAccount.Deserialize(Convert.FromBase64String(resp.Result.Value.Data[0]));
Console.WriteLine($"Pool Mint: {obj.PoolMint}");

Wallet.Wallet wallet = new Wallet.Wallet(MnemonicWords);

var tokenAMint = new Account();
Expand Down Expand Up @@ -99,7 +105,8 @@ public void Run()
Examples.PollConfirmedTx(txSig);

var swap = new Account();
var program = new TokenSwapProgram(swap);
var program = new TokenSwapProgram();
var swapAuthority = program.CreateAuthority(swap).pubkey;

var swapTokenAAccount= new Account();
var swapTokenBAccount = new Account();
Expand All @@ -119,7 +126,7 @@ public void Run()
.AddInstruction(TokenProgram.InitializeAccount(
swapTokenAAccount,
tokenAMint,
program.SwapAuthority
swapAuthority
))
.AddInstruction(TokenProgram.Transfer(
tokenAUserAccount,
Expand All @@ -137,7 +144,7 @@ public void Run()
.AddInstruction(TokenProgram.InitializeAccount(
swapTokenBAccount,
tokenBMint,
program.SwapAuthority
swapAuthority
))
.AddInstruction(TokenProgram.Transfer(
tokenBUserAccount,
Expand Down Expand Up @@ -168,7 +175,7 @@ public void Run()
.AddInstruction(TokenProgram.InitializeMint(
poolMint,
9,
program.SwapAuthority
swapAuthority
))
.AddInstruction(SystemProgram.CreateAccount(
wallet.Account,
Expand Down Expand Up @@ -206,11 +213,12 @@ public void Run()
.AddInstruction(SystemProgram.CreateAccount(
wallet.Account,
swap,
RpcClient.GetMinimumBalanceForRentExemption((long)program.TokenSwapAccountDataSize).Result,
program.TokenSwapAccountDataSize,
RpcClient.GetMinimumBalanceForRentExemption((long)TokenSwapProgram.TokenSwapAccountDataSize).Result,
TokenSwapProgram.TokenSwapAccountDataSize,
program.ProgramIdKey
))
.AddInstruction(program.Initialize(
swap,
swapTokenAAccount,
swapTokenBAccount,
poolMint,
Expand All @@ -231,7 +239,7 @@ public void Run()
))
.Build(new Account[] { wallet.Account, swap });
Console.WriteLine($"Swap Account: {swap}");
Console.WriteLine($"Swap Auth Account: {program.SwapAuthority}");
Console.WriteLine($"Swap Auth Account: {swapAuthority}");
Console.WriteLine($"Pool Mint Account: {poolMint}");
Console.WriteLine($"Pool User Account: {poolUserAccount}");
Console.WriteLine($"Pool Fee Account: {poolFeeAccount}");
Expand All @@ -244,6 +252,7 @@ public void Run()
.SetRecentBlockHash(blockHash.Result.Value.Blockhash)
.SetFeePayer(wallet.Account)
.AddInstruction(program.Swap(
swap,
wallet.Account,
tokenAUserAccount,
swapTokenAAccount,
Expand All @@ -264,6 +273,7 @@ public void Run()
.SetRecentBlockHash(blockHash.Result.Value.Blockhash)
.SetFeePayer(wallet.Account)
.AddInstruction(program.DepositAllTokenTypes(
swap,
wallet.Account,
tokenAUserAccount,
tokenBUserAccount,
Expand All @@ -284,6 +294,7 @@ public void Run()
.SetRecentBlockHash(blockHash.Result.Value.Blockhash)
.SetFeePayer(wallet.Account)
.AddInstruction(program.WithdrawAllTokenTypes(
swap,
wallet.Account,
poolMint,
poolUserAccount,
Expand All @@ -305,6 +316,7 @@ public void Run()
.SetRecentBlockHash(blockHash.Result.Value.Blockhash)
.SetFeePayer(wallet.Account)
.AddInstruction(program.DepositSingleTokenTypeExactAmountIn(
swap,
wallet.Account,
tokenAUserAccount,
swapTokenAAccount,
Expand All @@ -323,6 +335,7 @@ public void Run()
.SetRecentBlockHash(blockHash.Result.Value.Blockhash)
.SetFeePayer(wallet.Account)
.AddInstruction(program.WithdrawSingleTokenTypeExactAmountOut(
swap,
wallet.Account,
poolMint,
poolUserAccount,
Expand Down
39 changes: 39 additions & 0 deletions src/Solnet.Programs/Abstract/BaseProgram.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using Solnet.Wallet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Solnet.Programs.Abstract
{
/// <summary>
/// A class to abstract some of the core program commonality
/// </summary>
public abstract class BaseProgram : Program
{
private PublicKey _programIdKey;
private string _programName;

/// <summary>
/// The public key of the program.
/// </summary>
public virtual PublicKey ProgramIdKey => _programIdKey;

/// <summary>
/// The program's name.
/// </summary>
public virtual string ProgramName => _programName;

/// <summary>
/// Creates an instance of the base program class with specified id and name
/// </summary>
/// <param name="programIdKey">The program key</param>
/// <param name="programName">The program name</param>
protected BaseProgram(PublicKey programIdKey, string programName)
{
_programIdKey = programIdKey;
_programName = programName;
}
}
}
21 changes: 21 additions & 0 deletions src/Solnet.Programs/Abstract/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using Solnet.Wallet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Solnet.Programs.Abstract
{
public interface Program
{
/// <summary>
/// The program's key
/// </summary>
PublicKey ProgramIdKey { get; }
/// <summary>
/// The name of the program
/// </summary>
string ProgramName { get; }
}
}
18 changes: 18 additions & 0 deletions src/Solnet.Programs/TokenSwap/Models/Fees.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Buffers.Binary;
using Solnet.Programs.Utilities;

namespace Solnet.Programs.TokenSwap.Models
Expand Down Expand Up @@ -65,5 +66,22 @@ public Span<byte> Serialize()
ret.WriteU64(HostFeeDenomerator, 56);
return new Span<byte>(ret);
}

public static Fees Deserialize(byte[] bytes)
{
var span = new Span<byte>(bytes);
var f = new Fees()
{
TradeFeeNumerator = BinaryPrimitives.ReadUInt64LittleEndian(span.Slice(0, 8)),
TradeFeeDenominator = BinaryPrimitives.ReadUInt64LittleEndian(span.Slice(8, 8)),
OwnerTradeFeeNumerator = BinaryPrimitives.ReadUInt64LittleEndian(span.Slice(16, 8)),
OwnerTradeFeeDenomerator = BinaryPrimitives.ReadUInt64LittleEndian(span.Slice(24, 8)),
OwnerWithrawFeeNumerator = BinaryPrimitives.ReadUInt64LittleEndian(span.Slice(32, 8)),
OwnerWithrawFeeDenomerator = BinaryPrimitives.ReadUInt64LittleEndian(span.Slice(40, 8)),
HostFeeNumerator = BinaryPrimitives.ReadUInt64LittleEndian(span.Slice(48, 8)),
HostFeeDenomerator = BinaryPrimitives.ReadUInt64LittleEndian(span.Slice(56, 8)),
};
return f;
}
}
}
24 changes: 20 additions & 4 deletions src/Solnet.Programs/TokenSwap/Models/SwapCurve.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Solnet.Programs.Utilities;
using System;
using System.Buffers.Binary;

namespace Solnet.Programs.TokenSwap.Models
{
Expand All @@ -8,6 +9,11 @@ namespace Solnet.Programs.TokenSwap.Models
/// </summary>
public class SwapCurve
{
/// <summary>
/// The constant procuct curve
/// </summary>
public static SwapCurve ConstantProduct => new SwapCurve() { CurveType = CurveType.ConstantProduct, Calculator = new ConstantProductCurve() };

/// <summary>
/// The curve type.
/// </summary>
Expand Down Expand Up @@ -35,9 +41,19 @@ public virtual ReadOnlySpan<byte> Serialize()
return new Span<byte>(ret);
}

/// <summary>
/// The constant procuct curve
/// </summary>
public static SwapCurve ConstantProduct => new SwapCurve() { CurveType = CurveType.ConstantProduct, Calculator = new ConstantProductCurve() };
public static SwapCurve Deserialize(byte[] bytes)
{
var s = new SwapCurve()
{
CurveType = (CurveType)bytes[0],
//todo other curves
Calculator = new ConstantProductCurve()
};
if (s.CurveType != CurveType.ConstantProduct)
{
throw new NotSupportedException("Only constant product curves are supported by Solnet currently");
}
return s;
}
}
}
115 changes: 115 additions & 0 deletions src/Solnet.Programs/TokenSwap/Models/TokenSwapAccount.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
using Solnet.Wallet;

namespace Solnet.Programs.TokenSwap.Models
{

/// <summary>
/// TokenSwap program state
/// </summary>
public class TokenSwapAccount
{
/// <summary>
/// the size of this account in bytes
/// </summary>
public const int TOKEN_SWAP_DATA_LEN = 324;

/// <summary>
/// Versions of this state account
/// </summary>
public enum SwapVersion { SwapV1 = 1 }

/// <summary>
/// Version of this state account
/// </summary>
public SwapVersion Version;

/// <summary>
/// Initialized state
/// </summary>
public bool IsInitialized;

/// <summary>
/// Nonce used in program address.
/// The program address is created deterministically with the nonce,
/// swap program id, and swap account pubkey. This program address has
/// authority over the swap's token A account, token B account, and pool
/// token mint.
/// </summary>
public byte Nonce;

/// <summary>
/// Program ID of the tokens being exchanged.
/// </summary>
public PublicKey TokenProgramId;

/// <summary>
/// Token A
/// </summary>
public PublicKey TokenAAccount;

/// <summary>
/// Token B
/// </summary>
public PublicKey TokenBAccount;

/// <summary>
/// Pool tokens are issued when A or B tokens are deposited.
/// Pool tokens can be withdrawn back to the original A or B token.
/// </summary>
public PublicKey PoolMint;

/// <summary>
/// Mint information for token A
/// </summary>
public PublicKey TokenAMint;

/// <summary>
/// Mint information for token B
/// </summary>
public PublicKey TokenBMint;

/// <summary>
/// Pool token account to receive trading and / or withdrawal fees
/// </summary>
public PublicKey PoolFeeAccount;

/// <summary>
/// All fee information
/// </summary>
public Fees Fees;

/// <summary>
/// Swap curve parameters, to be unpacked and used by the SwapCurve, which
/// calculates swaps, deposits, and withdrawals
/// </summary>
public SwapCurve SwapCurve;

/// <summary>
/// Deserilize a token swap from the bytes of an account
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public static TokenSwapAccount Deserialize(byte[] data)
{
if (data.Length != TOKEN_SWAP_DATA_LEN)
return null;

var ret = new TokenSwapAccount()
{
Version = SwapVersion.SwapV1,
IsInitialized = data[1] == 1,
Nonce = data[2],
TokenProgramId = new PublicKey(data[3..35]),
TokenAAccount = new PublicKey(data[35..67]),
TokenBAccount = new PublicKey(data[67..99]),
PoolMint = new PublicKey(data[99..131]),
TokenAMint = new PublicKey(data[131..163]),
TokenBMint = new PublicKey(data[163..195]),
PoolFeeAccount = new PublicKey(data[195..227]),
Fees = Fees.Deserialize(data[227..291]),
SwapCurve = SwapCurve.Deserialize(data[291..]),
};
return ret;
}
}
}
Loading

0 comments on commit 966b71b

Please sign in to comment.