linera_sdk/abis/
fungible.rs

1// Copyright (c) Zefchain Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4//! An ABI for applications that implement a fungible token.
5
6use std::collections::BTreeMap;
7
8use async_graphql::{InputObject, Request, Response, SimpleObject};
9use linera_base::{
10    abi::{ContractAbi, ServiceAbi},
11    data_types::Amount,
12    identifiers::{AccountOwner, ChainId},
13};
14use linera_sdk_derive::GraphQLMutationRootInCrate;
15use serde::{Deserialize, Serialize};
16
17/// An operation
18#[derive(Debug, Deserialize, Serialize, GraphQLMutationRootInCrate)]
19pub enum NativeFungibleOperation {
20    /// Requests an account balance.
21    Balance {
22        /// Owner to query the balance for
23        owner: AccountOwner,
24    },
25    /// Requests this fungible token's ticker symbol.
26    TickerSymbol,
27    /// Transfers tokens from a (locally owned) account to a (possibly remote) account.
28    Transfer {
29        /// Owner to transfer from
30        owner: AccountOwner,
31        /// Amount to be transferred
32        amount: Amount,
33        /// Target account to transfer the amount to
34        target_account: Account,
35    },
36    /// Same as `Transfer` but the source account may be remote. Depending on its
37    /// configuration, the target chain may take time or refuse to process
38    /// the message.
39    Claim {
40        /// Source account to claim amount from
41        source_account: Account,
42        /// Amount to be claimed
43        amount: Amount,
44        /// Target account to claim the amount into
45        target_account: Account,
46    },
47}
48
49/// An ABI for applications that implement a fungible token.
50pub struct NativeFungibleTokenAbi;
51
52impl ContractAbi for NativeFungibleTokenAbi {
53    type Operation = NativeFungibleOperation;
54    type Response = FungibleResponse;
55}
56
57impl ServiceAbi for NativeFungibleTokenAbi {
58    type Query = Request;
59    type QueryResponse = Response;
60}
61
62/// An operation
63#[derive(Debug, Deserialize, Serialize, GraphQLMutationRootInCrate)]
64pub enum FungibleOperation {
65    /// Requests an account balance.
66    Balance {
67        /// Owner to query the balance for
68        owner: AccountOwner,
69    },
70    /// Requests this fungible token's ticker symbol.
71    TickerSymbol,
72    /// Approve the transfer of tokens
73    Approve {
74        /// Owner to transfer from
75        owner: AccountOwner,
76        /// The spender account
77        spender: AccountOwner,
78        /// Maximum amount to be transferred
79        allowance: Amount,
80    },
81    /// Transfers tokens from a (locally owned) account to a (possibly remote) account.
82    Transfer {
83        /// Owner to transfer from
84        owner: AccountOwner,
85        /// Amount to be transferred
86        amount: Amount,
87        /// Target account to transfer the amount to
88        target_account: Account,
89    },
90    /// Transfers tokens from a (locally owned) account to a (possibly remote) account by using the allowance.
91    TransferFrom {
92        /// Owner to transfer from
93        owner: AccountOwner,
94        /// The spender of the amount.
95        spender: AccountOwner,
96        /// Amount to be transferred
97        amount: Amount,
98        /// Target account to transfer the amount to
99        target_account: Account,
100    },
101    /// Same as `Transfer` but the source account may be remote. Depending on its
102    /// configuration, the target chain may take time or refuse to process
103    /// the message.
104    Claim {
105        /// Source account to claim amount from
106        source_account: Account,
107        /// Amount to be claimed
108        amount: Amount,
109        /// Target account to claim the amount into
110        target_account: Account,
111    },
112}
113
114/// An ABI for applications that implement a fungible token.
115pub struct FungibleTokenAbi;
116
117impl ContractAbi for FungibleTokenAbi {
118    type Operation = FungibleOperation;
119    type Response = FungibleResponse;
120}
121
122impl ServiceAbi for FungibleTokenAbi {
123    type Query = Request;
124    type QueryResponse = Response;
125}
126
127/// A native fungible response
128#[derive(Debug, Deserialize, Serialize, Default)]
129pub enum FungibleResponse {
130    /// OK response
131    #[default]
132    Ok,
133    /// Balance response
134    Balance(Amount),
135    /// Ticker symbol response
136    TickerSymbol(String),
137}
138
139/// The initial state to instantiate fungible with
140#[derive(Clone, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
141pub struct InitialState {
142    /// Accounts and their respective initial balances
143    pub accounts: BTreeMap<AccountOwner, Amount>,
144}
145
146/// The parameters to instantiate fungible with
147#[derive(Clone, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
148pub struct Parameters {
149    /// Ticker symbol for the fungible
150    pub ticker_symbol: String,
151}
152
153impl Parameters {
154    /// Instantiate parameters
155    pub fn new(ticker_symbol: &str) -> Self {
156        let ticker_symbol = ticker_symbol.to_string();
157        Self { ticker_symbol }
158    }
159}
160
161/// An account.
162#[derive(
163    Clone,
164    Copy,
165    Debug,
166    Deserialize,
167    Eq,
168    Ord,
169    PartialEq,
170    PartialOrd,
171    Serialize,
172    SimpleObject,
173    InputObject,
174)]
175#[graphql(input_name = "FungibleAccount")]
176pub struct Account {
177    /// Chain ID of the account
178    pub chain_id: ChainId,
179    /// Owner of the account
180    pub owner: AccountOwner,
181}
182
183/// A builder type for constructing the initial state of the application.
184#[derive(Debug, Default)]
185pub struct InitialStateBuilder {
186    /// Accounts and their respective initial balances
187    account_balances: BTreeMap<AccountOwner, Amount>,
188}
189
190impl InitialStateBuilder {
191    /// Adds an account to the initial state of the application.
192    pub fn with_account(mut self, account: AccountOwner, balance: impl Into<Amount>) -> Self {
193        self.account_balances.insert(account, balance.into());
194        self
195    }
196
197    /// Returns the serialized initial state of the application, ready to use as the
198    /// initialization argument.
199    pub fn build(&self) -> InitialState {
200        InitialState {
201            accounts: self.account_balances.clone(),
202        }
203    }
204}