- Initialization
- Connect SDK
- Wallet Events
- About Operations Execution
-
StableCoin
- Create
- Creates a simple stablecoin, with all keys set to the Smart Contracts
- Creates a simple stablecoin, with all keys set to the admin's public key
- Creates a simple stablecoin, with all keys set to none
- GetInfo
- GetBalanceOf
- GetBalanceOfHBAR
- Associate
- isAccountAssociated
- CashIn
- Burn
- Rescue
- Rescue HBAR
- Wipe
- Pause
- Unpause
- Freeze
- Unfreeze
- GrantKYC
- RevokeKYC
- IsAccountKYCGranted
- Transfers
- Update
- Delete
- GetReserveAddress
- UpdateReserveAddress
- Capabilities
- SignTransaction
- SubmitTransaction
- RemoveTransaction
- GetTransactions
- Proxy
- Network
- Event
- Account
- Role
- Reserve Data Feed
- Factory
- Common
- Tsconfig
- License
This project provides a SDK to manage Hedera tokens throughout their lifecycle.
This project is based on hybrid tokens, that is, it uses smart contracts that communicate with Hedera to interact with native tokens. It provides functionalities to use in server mode, as well as for web integration (currently supporting HashPack and Metamask).
For more information about the deployed contracts you can consult them in this project - Contracts.
If you want to see a server side implementation you can see it in this project - Standalone.
If you want to see an example of a React web app you can see it in this project - Web.
You will need the following supporting tools/frameworks installed:
- Run
npm install @hashgraph/stablecoin-npm-sdk
to install the dependency from NPM. - Import and use the SDK.
To use this project in development mode you must follow the steps indicated in the following section Build.
- Clone the repo and open a terminal in the root folder.
- Run
node install.js
. To install all the dependencies and links. -
cd
into./contracts
. - Run
npm run compile
to compile the contracts. - Run
npm run build
to build the contracts. -
cd
into./sdk
. - Make your changes.
- Run
npm run build
to build the SDK. - Import and use the SDK. Or use one of the example projects under
/examples
.
Before using the SDK we need to execute the Network.init
function and specify network details:
Example
import { LoggerTransports, SDK } from '@hashgraph/stablecoin-npm-sdk';
SDK.log = {
level: process.env.REACT_APP_LOG_LEVEL ?? 'ERROR',
transports: new LoggerTransports.Console(),
};
await Network.init(
new InitializationRequest({
network: 'testnet',
}),
);
In the configuration, you can also specify the factory contract address that will be invoked when creating a stablecoin.
const init = await Network.init(
new InitializationRequest({
network: 'testnet',
configuration: {
factoryAddress: '0.0.0'
},
}),
);
If you are using a backend (for multisignature transactions) you can also specify its url.
const init = await Network.init(
new InitializationRequest({
network: 'testnet',
backend: {
url: 'http://127.0.0.1:3001/api/'
},
}),
);
The next step would be to connect to the network. Currently, multiple types of connections are offered: Client (a Hedera account configured in an application configuration file), MetaMask, HashPack, fireblocks, DFNS, AWS-KMS and Multisig. These connection types are in the SupportedWallets enum.
export enum SupportedWallets {
METAMASK = 'Metamask',
HASHPACK = 'HashPack',
CLIENT = 'Client',
...
}
In addition to this we have to specify the accountId and private key for the Client, while HashPack and MetaMask do not require an account in the request.
Below are examples of each of them.
Client Example
await Network.connect(
new ConnectRequest({
account: {
accountId: account.accountId,
privateKey: {
key: account.privateKey.key,
type: account.privateKey.type,
},
},
network: 'testnet',
wallet: SupportedWallets.CLIENT,
}),
);
}
HashPack Example
await Network.connect(
new ConnectRequest({
network: 'testnet',
wallet: SupportedWallets.HASHPACK,
}),
);
}
MetaMask Example
await Network.connect(
new ConnectRequest({
network: 'testnet',
wallet: SupportedWallets.METAMASK,
}),
);
}
Wallets fire the following events, see Event.register for more info.
export enum WalletEvents {
walletInit = 'walletInit',
walletFound = 'walletFound',
walletPaired = 'walletPaired',
walletConnectionStatusChanged = 'walletConnectionStatusChanged',
walletAcknowledgeMessage = 'walletAcknowledgeMessage',
walletDisconnect = 'walletDisconnect',
}
This section explains all the operations offered by this SDK.
Before explaining all operations exposed by the SDK, is important to understand how some of these operations are going to be performed. When creating a stablecoin, a set of keys (wipe key, pause key, freeze key, etc...) must be provided in order to create the stablecoin token. Each of these keys will control, first of all, if the operation related with the key can be performed or not (if the token wipe key is not set, the wipe operation can not be performed), but, if a key is provided, depending on its value the operation could be performed through the stablecoin smart contract or through the Hedera SDK:
- If the token key corresponds to a Hedera account public key, the operation can only be performed by the Hedera account owning this public key, and only through the Hedera SDK.
- If the token key corresponds to the stablecoin smart contract administrator key, the operation can only be performed through the smart contract, so whoever calls the smart contract can perform the operation. To prevent anyone from performing certain operations roles are used. When the need for a role is indicated in an operation's description, this is only when the related key of the stablecoin token is configured to be the smart contract admin key.
The multisig wallet mode is a special one. Operations executed when connected as "multisig" will not be submitted to the Hedera DLT, instead they will be stored in a backend waiting for the multisig account key owners to sign it. Once the operation has been signed by all the required keys it will be ready for submission to the Hedera DLT.
The following operations represent most of the operations that can be performed using a stablecoin. Some of them can be performed through the stablecoin smart contract or through the Hedera SDK depending on the token configuration explained above.
Creates a new stablecoin. You must use Network.connect
first with a SupportedWallet
.
Spec:
interface CreateRequest {
name: string;
symbol: string;
decimals: number | string;
initialSupply?: string;
maxSupply?: string;
freezeDefault?: boolean;
freezeKey?: RequestPublicKey;
KYCKey?: RequestPublicKey;
wipeKey?: RequestPublicKey;
pauseKey?: RequestPublicKey;
supplyType?: TokenSupplyType;
feeScheduleKey?: RequestPublicKey;
stableCoinFactory: string;
hederaTokenManager: string;
reserveAddress?: string;
reserveInitialAmount?: string;
createReserve: boolean;
grantKYCToOriginalSender?: boolean;
burnRoleAccount?: string | undefined;
wipeRoleAccount?: string | undefined;
rescueRoleAccount?: string | undefined;
pauseRoleAccount?: string | undefined;
freezeRoleAccount?: string | undefined;
deleteRoleAccount?: string | undefined;
kycRoleAccount?: string | undefined;
cashInRoleAccount?: string | undefined;
cashInRoleAllowance?: string | undefined;
feeRoleAccount?: string | undefined;
metadata?: string | undefined;
proxyAdminOwnerAccount?: string;
}
StableCoin.create = (request: CreateRequest): Promise<StableCoinViewModel>
Example:
This delegates access to features to the smart contract, and enables the usage of roles so multiple accounts can have the same role. The accounts to which the roles are granted can be set in this operation or later on, once the stablecoin was created.
import {
FactoryAddressTestnet,
HederaTokenManagerAddressTestnet,
Account,
CreateRequest,
} from '@hashgraph/stablecoin-npm-sdk';
const stableCoin: StableCoinViewModel = await StableCoin.create(
new CreateRequest({
name: 'Hedera stablecoin',
symbol: 'HSC',
decimals: 6,
kycKey: Account.NullPublicKey,
wipeKey: Account.NullPublicKey,
pauseKey: Account.NullPublicKey,
adminKey: Account.NullPublicKey,
freezeKey: Account.NullPublicKey,
hederaTokenManager: HederaTokenManagerAddressTestnet,
stableCoinFactory: FactoryAddressTestnet,
createReserve: false,
metadata: 'metadata'
})
);
By specifying the public key of an account, we can set the stablecoin's keys to be the admin's enabling all features through the Hedera Token Service. In this scenario, only one account could be in charge of one or several operations, but is not possible to multiple accounts to be in charge of one operation.
import {
FactoryAddressTestnet,
HederaTokenManagerAddressTestnet,
Account,
CreateRequest,
} from '@hashgraph/stablecoin-npm-sdk';
const privateKey: RequestPrivateKey = {
key: 'someKey',
type: 'ED25519',
};
const reqAccount: RequestAccount = {
accountId: '0.0.1',
privateKey: privateKey,
};
const req: GetPublicKeyRequest = new GetPublicKeyRequest({
account: reqAccount,
});
const publicKey = Account.getPublicKey(req);
const stableCoin: StableCoinViewModel = await StableCoin.create(
new CreateRequest({
name: 'Hedera stablecoin',
symbol: 'HSC',
decimals: 6,
kycKey: publicKey,
wipeKey: publicKey,
pauseKey: publicKey,
adminKey: publicKey,
freezeKey: publicKey,
hederaTokenManager: HederaTokenManagerAddressTestnet,
stableCoinFactory: FactoryAddressTestnet,
createReserve: false,
metadata: 'metadata',
proxyAdminOwnerAccount: '0.0.13579'
})
);
In the above exmaple, it is also important to notice that, when creating a stablecoin, the proxyAdminOwnerAccount
parameter in the CreateRequest
class, allows the user to configure an account id, which may be a contract like a timelock controller, a cold wallet, etc, to be the stablecoin proxy admin owner rather than the account id that is creating the stablecoin, which is the default option if the user doesn't populate this optional parameter.
By not setting any of the keys, the stablecoin will have the corresponding features disabled and the keys set to none.
import {
FactoryAddressTestnet,
HederaTokenManagerAddressTestnet,
Account,
CreateRequest,
} from '@hashgraph/stablecoin-npm-sdk';
const stableCoin: StableCoinViewModel = await StableCoin.create(
new CreateRequest({
name: 'Hedera stablecoin',
symbol: 'HSC',
decimals: 6,
hederaTokenManager: HederaTokenManagerAddressTestnet,
stableCoinFactory: FactoryAddressTestnet,
createReserve: false
})
);
Gets the information of an existing stablecoin.
Spec:
StableCoin.getInfo = (request: GetStableCoinDetailsRequest): Promise<StableCoinViewModel>
Example:
const stableCoin: StableCoinViewModel = await StableCoin.getInfo(
new GetStableCoinDetailsRequest({
id: '0.0.1'
})
);
Gets the balance of tokens for an account.
Spec:
StableCoin.getBalanceOf = (request: GetAccountBalanceRequest): Promise<Balance>
type Balance = {
value: BigDecimal
}
Example:
const result: Balance = await StableCoin.getBalanceOf(
new GetAccountBalanceRequest({
tokenId: '0.0.1',
targetId: '0.0.2'
})
);
result.toString()
result.decimals
Gets the balance of HBARs for an account.
Spec:
StableCoin.getBalanceOfHBAR = (request: GetAccountBalanceHBARRequest): Promise<Balance>
type Balance = {
value: BigDecimal
}
Example:
const result: Balance = await StableCoin.getBalanceOfHBAR(
new GetAccountBalanceHBARRequest({
treasuryAccountId: '0.0.1'
})
);
result.toString()
result.decimals
Associates a stablecoin with an account.
Spec:
StableCoin.associate = (request: AssociateTokenRequest): Promise<boolean>
Example:
const result: boolean = await StableCoin.associate(
new AssociateTokenRequest({
account: new HashPackAccount('0.0.1')
})
);
Checks if an account is associated with a stablecoin.
Spec:
StableCoin.isAccountAssociated = (request: IsAccountAssociatedTokenRequest): Promise<boolean>
Example:
const result: boolean = await StableCoin.isAccountAssociated(
new IsAccountAssociatedTokenRequest({
tokenId: '0.0.1',
targetId: '0.0.2'
})
);
Mints tokens and then transfers to an account. The operating account must have the supplier role.
Spec:
StableCoin.cashIn = (request: CashInRequest): Promise<boolean>
Example:
const result: boolean = await StableCoin.cashIn(
new CashInRequest({
tokenId: '0.0.1',
targetId: '0.0.2',
amount: '1234'
})
);
Burns an amount of tokens existing in the treasury account. The operating account must have the burn role.
Spec:
StableCoin.burn = (request: BurnRequest): Promise<boolean>
Example:
const result: boolean = await StableCoin.burn(
new BurnRequest({
tokenId: '0.0.1',
amount: '1234'
})
);
Transfers an amount of tokens existing in the treasury account to the account that invokes the operation. The operating account must have the rescue role.
Spec:
StableCoin.rescue = (request: RescueRequest): Promise<boolean>
Example:
const result: boolean = await StableCoin.rescue(
new RescueRequest({
tokenId: '0.0.1',
amount: '1234'
})
);
Transfers an amount of HBARs existing in the treasury account to the account that invokes the operation. The operating account must have the rescue role.
Spec:
StableCoin.rescueHBAR = (request: RescueHBARRequest): Promise<boolean>
Example:
const result: boolean = await StableCoin.rescueHBAR(
new RescueHBARRequest({
tokenId: '0.0.1',
amount: '1234'
})
);
Wipes an amount of tokens from an account. The operating account must have the wipe role.
Spec:
StableCoin.wipe = (request: WipeRequest): Promise<boolean>
Example:
const result: boolean = await StableCoin.wipe(
new WipeRequest({
tokenId: '0.0.1',
targetId: '0.0.2',
amount: '1234'
})
);
Pauses a stablecoin. None of the operations can be taken while the stablecoin is in paused state. The operating account must have the pause role.
Spec:
StableCoin.pause = (request: PauseRequest): Promise<boolean>
Example:
const result: boolean = await StableCoin.pause(
new PauseRequest({
tokenId: '0.0.1'
})
);
Unpauses a stablecoin. If the stablecoin is not paused it will throw an exception. The operating account must have the pause role.
Spec:
StableCoin.unPause = (request: PauseRequest): Promise<boolean>
Example:
await StableCoin.unPause(
new PauseRequest({
tokenId: '0.0.1'
})
);
Prevents transfer of a stablecoin to/from an account. The operating account must have the freeze role.
Spec:
StableCoin.freeze = (request: FreezeRequest): Promise<boolean>
Example:
const result: boolean = await StableCoin.freeze(
new FreezeRequest({
tokenId: '0.0.1',
targetId: '0.0.2'
})
);
Enables transfer of a stablecoin to/from an account. The operating account must have the freeze role.
Spec:
StableCoin.unFreeze = (request: FreezeRequest): Promise<boolean>
Example:
await StableCoin.unFreeze(
new FreezeRequest({
tokenId: '0.0.1',
targetId: '0.0.2'
})
);
Grants KYC to an account. If a Token has KYC enabled, only accounts with KYC can operate it. The operating account must have the KYC role.
Spec:
StableCoin.grantKyc(request: KYCRequest): Promise<boolean>
Example:
const result: boolean = await StableCoin.grantKyc(
new KYCRequest({
tokenId: '0.0.1',
targetId: '0.0.2'
})
);
Revokes KYC from an account. If a Token has KYC enabled, only accounts with KYC can operate it. The operating account must have the KYC role.
Spec:
StableCoin.revokeKyc(request: KYCRequest): Promise<boolean>
Example:
await StableCoin.revokeKyc(
new KYCRequest({
tokenId: '0.0.1',
targetId: '0.0.2'
})
);
Checks if an account has the KYC granted.
Spec:
StableCoin.isAccountKYCGranted(request: KYCRequest): Promise<boolean>
Example:
await StableCoin.isAccountKYCGranted(
new KYCRequest({
tokenId: '0.0.1',
targetId: '0.0.2'
})
);
Transfer tokens from an account to up to 9 accounts. This operation is always performed through the Hedera SDK.
Spec:
StableCoin.transfers(request: TransfersRequest): Promise<boolean>
Example:
await StableCoin.transfers(
new TransfersRequest({
targetIds: ['0.0.1', '0.0.2', '0.0.3'],
amounts: ['1', '2', '3'],
tokenId: '0.0.4',
targetId: '0.0.5'
})
);
Updates certain properties of a token. The operating account must have the admin role.
Spec:
interface UpdateRequest {
tokenId: string;
name?: string;
symbol?: string;
autoRenewPeriod?: string;
expirationTimestamp?: string;
freezeKey?: RequestPublicKey;
kycKey?: RequestPublicKey;
wipeKey?: RequestPublicKey;
pauseKey?: RequestPublicKey;
feeScheduleKey?: RequestPublicKey;
metadata?: string | undefined;
}
StableCoin.update(request: UpdateRequest): Promise<boolean>
Example:
import {
FactoryAddressTestnet,
HederaTokenManagerAddressTestnet,
Account,
CreateRequest
} from '@hashgraph/stablecoin-npm-sdk';
const privateKey: RequestPrivateKey = {
key: 'someKey',
type: 'ED25519'
};
const reqAccount: RequestAccount = {
accountId: '0.0.1',
privateKey: privateKey
};
const req: GetPublicKeyRequest = new GetPublicKeyRequest({
account: reqAccount
});
const publicKey = Account.getPublicKey(req);
await StableCoin.update(
new UpdateRequest({
tokenId: '0.0.1',
name: 'new token name',
symbol: 'new token symbol',
autoRenewPeriod: '7776000',
expirationTimestamp: '1684318075000',
freezeKey: publicKey,
kycKey: publicKey,
wipeKey: publicKey,
pauseKey: publicKey,
feeScheduleKey: publicKey,
metadata: 'new metadata'
})
);
Deletes a stablecoin. Important this operation is not reversible. The operating account must have the admin role.
Spec:
StableCoin.delete = (request: DeleteRequest): Promise<boolean>
Example:
await StableCoin.delete(
new DeleteRequest({
tokenId: '0.0.1',
})
);
Gets the contract reserve address.
Spec:
StableCoin.getReserveAddress(request: GetReserveAddressRequest): Promise<string>;
Example:
const result: string = await StableCoin.getReserveAddress(
new GetReserveAddressRequest({
tokenId: '0.0.1',
})
);
Updates the contract reserve address.
Spec:
StableCoin.updateReserveAddress = (request: UpdateReserveAddressRequest,): Promise<boolean>;
Example:
const result: boolean = await StableCoin.updateReserveAddress(
new GetReserveAddressRequest({
tokenId: '0.0.1',
reserveAddress: '0.0.54445787'
})
);
Get capabilities for an account for a stablecoin. Each capability determines the type of operation that can be performed (cash in, burn, wipe, etc...) and on whether it should be done via the smart contract for the stablecoin (proxyAddress in the coin: StableCoin
attribute) or through the Hedera Token Service.
See the spec below for all the attributes you can get from the request.
Spec:
StableCoin.capabiltities = (request: CapabilitiesRequest): Promise<StableCoinCapabilities>
class StableCoinCapabilities {
constructor(
public readonly coin: StableCoin,
public readonly capabilities: Capability[],
public readonly account: Account,
) {}
}
enum Operation {
CASH_IN = 'Cash_in',
BURN = 'Burn',
WIPE = 'Wipe',
FREEZE = 'Freeze',
UNFREEZE = 'Unfreeze',
PAUSE = 'Pause',
UNPAUSE = 'Unpause',
DELETE = 'Delete',
RESCUE = 'Rescue',
RESCUE_HBAR = 'Rescue_HBAR'
ROLE_MANAGEMENT = 'Role_Management',
ROLE_ADMIN_MANAGEMENT = 'Admin_Role',
RESERVE_MANAGEMENT = 'Admin_Role',
GRANT_KYC = 'Grant_KYC',
REVOKE_KYC = 'Revoke_KYC',
}
enum Access {
HTS,
CONTRACT,
}
class Capability {
constructor(
public readonly operation: Operation,
public readonly access: Access,
) {}
}
class Account {
constructor(
public id: HederaId;
public evmAddress?: string;
public privateKey?: PrivateKey;
public publicKey?: PublicKey;
) {}
}
class StableCoin {
constructor(
public name: string;
public symbol: string;
public decimals: number;
public adminKey?: PublicKey | ContractId;
public initialSupply?: BigDecimal;
public totalSupply?: BigDecimal;
public maxSupply?: BigDecimal;
public memo?: string;
public proxyAddress?: HederaId;
public evmProxyAddress?: string;
public freezeKey?: PublicKey | ContractId;
public freezeDefault?: boolean;
public kycKey?: PublicKey | ContractId;
public wipeKey?: PublicKey | ContractId;
public pauseKey?: PublicKey | ContractId;
public paused?: boolean;
public supplyKey?: PublicKey | ContractId;
public treasury?: HederaId;
public tokenType?: TokenType;
public supplyType?: TokenSupplyType;
public tokenId?: HederaId;
public autoRenewAccount?: HederaId;
public autoRenewAccountPeriod?: number;
public deleted?: boolean;
) {}
}
Example:
const result: StableCoinCapabilities = await StableCoin.capabiltities(
new GetAccountBalanceRequest({
account: {
accountId: "0.0.1"
},
tokenId: "0.0.2"
})
);
Signs a multisig transaction stored in the backend.
Spec:
StableCoin.signTransaction = (request: SignTransactionRequest): Promise<boolean>;
Example:
const result: boolean = await StableCoin.signTransaction(
new SignTransactionRequest({
transactionId: 'f8ff7778-1cbd-429a-acf3-bfc92c5fe875',
})
);
Submits a multisig transaction stored in the backend. The transaction must have been previously signed by all required keys
Spec:
StableCoin.submitTransaction = (request: SubmitTransactionRequest): Promise<boolean>;
Example:
const result: boolean = await StableCoin.submitTransaction(
new SubmitTransactionRequest({
transactionId: 'f8ff7778-1cbd-429a-acf3-bfc92c5fe875',
})
);
Removes a multisig transaction stored in the backend.
Spec:
StableCoin.removeTransaction = (request: RemoveTransactionRequest): Promise<boolean>;
Example:
const result: boolean = await StableCoin.removeTransaction(
new RemoveTransactionRequest({
transactionId: 'f8ff7778-1cbd-429a-acf3-bfc92c5fe875',
})
);
Retrieves multisig transactions from the backend.
Spec:
StableCoin.getTransactions = (request: GetTransactionsRequest): Promise<MultiSigTransactionsViewModel>;
Example:
const result: MultiSigTransactionsViewModel = await StableCoin.getTransactions(
new GetTransactionsRequest({
page: 1,
limit: 10,
account: '0.0.1'
})
);
The following functions allow the user to both get information and execute operations regarding the stablecoin proxy contract.
Gets the configuration about the stablecoin proxy: the HederaTokenManager contract implementation address and the proxy admin account that allows to change the previous implementation.
Spec:
Proxy.getProxyConfig(request: GetProxyConfigRequest): Promise<ProxyConfigurationViewModel>;
Example:
const result: ProxyConfigurationViewModel = await Proxy.getProxyConfig(
new GetProxyConfigRequest({
tokenId: '0.0.1',
})
);
Proposes the change of the HederaTokenManager contract proxy admin owner.
Spec:
Proxy.changeProxyOwner(request: ChangeProxyOwnerRequest): Promise<boolean>;
Example:
const result: boolean = await Proxy.changeProxyOwner(
new ChangeProxyOwnerRequest({
tokenId: '0.0.1',
targetId: '0.0.2'
})
);
A proposed account accepts the change to be the new HederaTokenManager contract proxy admin owner.
Spec:
Proxy.acceptProxyOwner(request: AcceptProxyOwnerRequest): Promise<boolean>;
Example:
const result: boolean = await Proxy.acceptProxyOwner(
new AcceptProxyOwnerRequest({
tokenId: '0.0.1',
targetId: '0.0.2'
})
);
Updates the HederaTokenManager contract implementation address.
Spec:
Proxy.upgradeImplementation(request: UpgradeImplementationRequest): Promise<boolean>;
Example:
const result: boolean = await Proxy.upgradeImplementation(
new UpgradeImplementationRequest({
tokenId: '0.0.1',
implementationAddress: '0.0.2'
})
);
Gets the factory implementation contract address and the factory proxy owner account.
Spec:
Proxy.getFactoryProxyConfig(request: GetFactoryProxyConfigRequest): Promise<ProxyConfigurationViewModel>;
Example:
const result: ProxyConfigurationViewModel = await Proxy.getFactoryProxyConfig(
new GetFactoryProxyConfigRequest({
factoryId: '0.0.1'
})
);
Upgrades the factory with a new factory implementation contract. Only the owner of the factory proxy can perform this action.
Spec:
Proxy.upgradeFactoryImplementation(request: UpgradeFactoryImplementationRequest): Promise<boolean>;
Example:
const result: boolean = await Proxy.upgradeFactoryImplementation(
new UpgradeFactoryImplementationRequest({
factoryId: '0.0.1',
implementationAddress: '0.0.2'
})
);
Changes the owner of the factory proxy. Only the owner of the factory proxy can perform this action.
Spec:
Proxy.changeFactoryProxyOwner(request: ChangeFactoryProxyOwnerRequest): Promise<boolean>;
Example:
const result: boolean = await Proxy.changeFactoryProxyOwner(
new ChangeFactoryProxyOwnerRequest({
factoryId: '0.0.1',
targetId: '0.0.2'
})
);
Establishes the connection to work with an existing Hedera account in a wallet in a certain Hedera network, also setting the mirror node and JSON-RPC-Relay services to use in the connection.
Spec:
Network.connect(req: ConnectRequest): Promise<InitializationData>;
Example:
await Network.connect(
new ConnectRequest({
network: 'testnet',
mirrorNode: {
name: 'mirrorNode',
baseUrl: 'https://testnet.mirrornode.hedera.com/'
},
rpcNode: {
name: 'rpcNode',
baseUrl: 'https://testnet.hashio.io/api'
},
wallet: SupportedWallets.HASHPACK
})
);
Disconnects the previously established connection.
Spec:
Network.disconnect(): Promise<boolean>;
Example:
await Network.disconnect();
Sets the network and could also set the mirror node and the JSON-RPC-Relay services, the factory smart contract address and register the events, returning supported wallets depending on wheter the SDK was started through a DApp or not.
Spec:
Network.init(req: InitializationRequest): Promise<SupportedWallets[]>;
Example:
await Network.init(
new InitializationRequest({
network: 'testnet',
mirrorNode: {
name: 'mirrorNode',
baseUrl: 'https://testnet.mirrornode.hedera.com/'
},
rpcNode: {
name: 'rpcNode',
baseUrl: 'https://testnet.hashio.io/api'
},
configuration: {
factoryAddress: '0.0.1'
}
})
);
Configures a Hedera network, setting some properties like environment and the mirror node and JSON-RPC-Relay services, and also, and optionally, the list of consensus nodes.
Spec:
Network.setNetwork(req: SetNetworkRequest): Promise<NetworkResponse>;
Example:
await Network.setNetwork(
new SetNetworkRequest({
enviroment: 'testnet',
mirrorNode: 'https://testnet.mirrornode.hedera.com/',
rpcNode: 'https://testnet.hashio.io/api',
consensusNodes: []
})
);
Gets the Hedera network you are currently working in.
Spec:
Network.getNetwork(): string;
Example:
Network.getNetwork();
Checks if the Hedera network you are currently working in is an existing Hedera network.
Spec:
Network.isNetworkRecognized(): boolean;
Example:
Network.isNetworkRecognized();
Sets the factory smart contract address in the configuration object.
Spec:
Network.setConfig(req: SetNetworkRequest): Promise<ConfigResponse>;
Example:
await Network.setConfig(
new SetConfigurationRequest({
factoryAddress: '0.0.1'
})
);
Sets the backend url.
Spec:
Network.setBackend(req: SetBackendRequest): Promise<BackendResponse>;
Example:
await Network.setBackend(
new SetBackendRequest({
url: 'http://127.0.0.1:3001/api'
})
);
Gets the factory smart contract address.
Spec:
Network.getFactoryAddress(): string;
Example:
Network.getFactoryAddress();
Registers for wallet events. All event listeners are optional, just make sure to call it before trying to pair with any wallet, since pairing events can occur right when the page loads and the extension is found, if the wallet was paired previously.
Multiple wallets can emit events, so make sure to filter them by the wallet
attribute available in all of them indicating which wallet is emitting the event. All supported wallets emit the same events.
All events use the standard node event emitting system and listeners are fully TS typed.
Spec:
Event.register = (events: Partial<WalletEvent>): void;
type WalletEvent = {
walletInit: (data: WalletInitEvent) => void;
walletFound: (data: WalletFoundEvent) => void;
walletPaired: (data: WalletPairedEvent) => void;
walletConnectionStatusChanged: (
data: WalletConnectionStatusChangedEvent,
) => void;
walletAcknowledgeMessage: (data: WalletAcknowledgeMessageEvent) => void;
walletDisconnect: (data: WalletBaseEvent) => void;
};
interface WalletBaseEvent {
wallet: SupportedWallets;
}
interface WalletInitEvent extends WalletBaseEvent {
initData: InitializationData;
}
interface WalletFoundEvent extends WalletBaseEvent {
name: string;
}
interface WalletPairedEvent extends WalletBaseEvent {
data: InitializationData;
network: Environment;
}
interface WalletConnectionStatusChangedEvent extends WalletBaseEvent {
status: ConnectionState;
}
interface WalletAcknowledgeMessageEvent extends WalletBaseEvent {
result: boolean;
}
Example:
Check out Router.tsx from the web repository for a comprehensive example in React of how to subscribe to events.
The following operations give information about Hedera accounts using Hedera mirror nodes, so do not imply any cost.
Gets the account public key.
Spec:
Account.getPublicKey(request: GetPublicKeyRequest): Promise<PublicKey>;
Example:
await Account.getPublicKey(
new GetPublicKeyRequest({
account: '0.0.1';
})
);
Gets a list of stablecoins associated with an account.
Spec:
Account.listStableCoins(request: GetListStableCoinRequest,): Promise<StableCoinListViewModel>;
Example:
await Account.listStableCoins(
new GetPublicKeyRequest({
account: '0.0.1';
})
);
Gets an account information.
Spec:
Account.getInfo(request: GetAccountInfoRequest): Promise<AccountViewModel>;
Example:
await Account.getInfo(
new GetAccountInfoRequest({
account: '0.0.1';
})
);
Roles allow Hedera accounts to perform certain operations on a stablecoin through the smart contracts. Operations that can be performed through Hedera SDK, due to the token configuration, do not need any role to be assigned. The management of roles can only be performed by a Hedera account having the admin role.
Checks if an account has a specific role for a stablecoin.
Spec:
Role.hasRole(request: HasRoleRequest): Promise<boolean>;
Example:
await Role.hasRole(
new HasRoleRequest({
tokenId: '0.0.1',
targetId: '0.046172343',
role: StableCoinRole.CASHIN_ROLE
})
);
Grants a role to an account for a stablecoin. The operating account must have the admin role.
Spec:
Role.grantRole(request: GrantRoleRequest): Promise<boolean>;
Example:
await Role.grantRole(
new GrantRoleRequest({
targetId: '0.0.1'
tokenId: '0.0.2',
role: StableCoinRole.CASHIN_ROLE,
})
);
Grants multiple roles to multiple accounts for a stablecoin. The operating account must have the admin role.
Spec:
Role.grantMultiRoles(request: GrantMultiRolesRequest): Promise<boolean>;
Example:
await Role.grantMultiRoles(
new GrantMultiRolesRequest({
targetsId: ['0.0.1', '0.0.2']
tokenId: '0.0.3',
roles: [StableCoinRole.CASHIN_ROLE, StableCoinRole.BURN_ROLE],
amounts: [1, 2]
})
);
Revokes a role of an account for a stablecoin. The operating account must have the admin role.
Spec:
Role.revokeRole(request: RevokeRoleRequest): Promise<boolean>;
Example:
await Role.revokeRole(
new RevokeRoleRequest({
targetId: '0.0.1'
tokenId: '0.0.2',
role: StableCoinRole.CASHIN_ROLE
})
);
Revokes multiple roles from multiple accounts for a stablecoin. The operating account must have the admin role.
Spec:
Role.revokeMultiRoles(request: RevokeMultiRolesRequest): Promise<boolean>;
Example:
await Role.revokeMultiRoles(
new RevokeMultiRolesRequest({
targetsId: ['0.0.1', '0.0.2']
tokenId: '0.0.3',
roles: [StableCoinRole.CASHIN_ROLE,StableCoinRole.BURN_ROLE]
})
);
Gets a list of all roles a Hedera account has for a stablecoin.
Spec:
Role.getRoles(request: GetRolesRequest): Promise<string[]>;
Example:
await Role.getRoles(
new GetRolesRequest({
targetId: '0.0.1',
tokenId: '0.0.2'
})
);
Gets a list of all Hedera accounts that have been granted a certain role.
Spec:
Role.getAccountsWithRoles(request: GetRolesRequest): Promise<string[]>;
Example:
await Role.getAccountsWithRoles(
new GetAccountsWithRolesRequest({
roleId: StableCoinRole.CASHIN_ROLE,
tokenId: '0.0.2'
})
);
Gets the supplier allowance (amount of tokens that can be minted by an account) for an account and a stablecoin.
Spec:
Role.getAllowance(request: GetSupplierAllowanceRequest): Promise<Balance>;
Example:
await Role.getAllowance(
new GetSupplierAllowanceRequest({
targetId: '0.0.1'
tokenId: '0.0.2',
})
);
Sets the supplier allowance to 0 for an account and a stablecoin. The operating account must have the admin role.
Spec:
Role.resetAllowance(request: ResetSupplierAllowanceRequest): Promise<boolean>;
Example:
await Role.resetAllowance(
new ResetSupplierAllowanceRequest({
targetId: '0.0.1'
tokenId: '0.0.2'
})
);
Increases the supplier allowance amount for an account and a stablecoin. The operating account must have the admin role.
Spec:
Role.increaseAllowance(request: IncreaseSupplierAllowanceRequest): Promise<boolean>;
Example:
await Role.increaseAllowance(
new IncreaseSupplierAllowanceRequest({
targetId: '0.0.1'
tokenId: '0.0.2',
amount: 1000
})
);
Decreases the supplier allowance amount for an account and a stablecoin. The operating account must have the admin role.
Spec:
Role.decreaseAllowance(request: DecreaseSupplierAllowanceRequest): Promise<boolean>;
Example:
await Role.decreaseAllowance(
new DecreaseSupplierAllowanceRequest({
targetId: '0.0.1'
tokenId: '0.0.2',
amount: 1000
})
);
Checks if an account has a limited supplier allowance for a stablecoin or not.
Spec:
Role.isLimited(request: CheckSupplierLimitRequest): Promise<boolean>;
Example:
await Role.isLimited(
new CheckSupplierLimitRequest({
targetId: '0.0.1'
tokenId: '0.0.2',
supplierType: 'limited'
})
);
Checks if an account has an unlimited supplier allowance for a stablecoin or not.
Spec:
Role.isUnlimited(request: CheckSupplierLimitRequest): Promise<boolean>;
Example:
await Role.isUnlimited(
new CheckSupplierLimitRequest({
targetId: '0.0.1'
tokenId: '0.0.2',
supplierType: 'unlimited'
})
);
The following operations are always performed through smart contracts calls, since the reserve data feed is a contract which can be deployed alongside the stablecoin. Getting the reserve amount can be performed by anyone while updating this amount can only be performed by accounts with the appropriate role.
Gets the reserve amount for a stablecoin.
Spec:
ReserveDataFeed.getReserveAmount = (request: GetReserveAmountRequest): Promise<Balance>;
Example:
const balance:Balance = await ReserveDataFeed.getReserveAmount(
new GetReserveAmountRequest({
tokenId: "0.0.1"
})
);
Updates the reserve amount for a stablecoin. The operating account must have the admin role.
Spec:
ReserveDataFeed.updateReserveAmount = (request: UpdateReserveAmountRequest): Promise<boolean>
Example:
const balance:boolean = await ReserveDataFeed.updateReserveAmount(
new UpdateReserveAmountRequest({
reserveAddress: '0.0.1',
reserveAmount: 1
})
);
The following operations are always performed through smart contracts calls.
Get a list of HederaTokenManager smart contract addresses stored in the factory.
Spec:
Factory.getHederaTokenManagerList = (request: GetTokenManagerListRequest): Promise<ContractId[]>;
Example
const list = await Factory.getHederaTokenManagerList(
new GetTokenManagerListRequest({
factoryId: '0.0.1'
})
);
The SDK class is exported. This static class enables the log level and application metadata to be set at any point in your code, just import it and change the values.
We use winston under the hood for logging, so all transports are exported from the SDK under LoggerTransports
for you to use. Refer to the documentation for more information on what transports are available.
import { LoggerTransports, SDK } from '@hashgraph/stablecoin-npm-sdk';
const { Console } = LoggerTransports;
SDK.appMetadata = {
name: 'Hedera stablecoin',
description: 'Example application',
icon: 'https://example.png',
url: '',
};
SDK.log = {
level: 'ERROR', // or 'WARN', 'INFO', 'HTTP', 'VERBOSE', 'DEBUG', 'SILLY'
transports: new Console(),
};
The project uses Jest for testing. To execute the tests, simply run npm run test
in the terminal, this will output the coverage as well.
Typescript 4.7 or higher is highly recommended to work with the SDK.
An example of a tsconfig.json for client-side applications (React):
{
"compilerOptions": {
"noImplicitAny": true,
"allowJs": false,
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "node",
"declaration": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"jsx": "react-jsx",
"types": ["node", "jest"],
"resolveJsonModule": true
},
"include": ["src", "svg.d.ts"],
"exclude": ["node_modules"]
}
An example of a tsconfig.json for server-side applications (Node):
{
"compilerOptions": {
"target": "es2016",
"module": "commonjs",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
}
}
If you have a question on how to use the product, please see our support guide.
Contributions are welcome. Please see the contributing guide to see how you can get involved.
This project is governed by the Contributor Covenant Code of Conduct. By participating, you are expected to uphold this code of conduct. Please report unacceptable behavior to oss@hedera.com.