Pond is an easy way to set up a local Kujira development chain.
It creates one or more local Cosmos chains and connects them via IBC, sets up price feeders for the on-chain oracle and deploys a set of Kujira core smart contracts.
Because Pond is meant to help builders on Kujira, its first and default chain will always be a Kujira chain and some of the commands (like deploy
or gov
) may only work here.
Requires docker and golang >=1.21
make install
Init creates all required configurations for validator nodes, price feeders and the IBC relayer.
The default configuration sets up a single Kujira chain with one validator node.
pond init
Set the number of validator nodes on the main (Kujira) chain. The default value is one, maximum is nine.
pond init --nodes 3
If you need different or more partner chains, thats possible too. All chains will be connected to the first (Kujira) chain.
pond init --chains cosmoshub
pond init --chains kujira,kujira,terra2
Pond will deploy a set of Kujira core contracts on its first start. If you want addtional contracts, you can provide the list with:
pond init --contracts kujira
Or deploy none:
pond init --no-contracts
Pond will forward all necessary ports to localhost
. If you want to make your pond available from outside your machine and make it available for others, you can provide an ip address to bind to:
pond init --listen 1.2.3.4
The default unbonding time is set to 14 days. If you need to test staking related scenarios, you can set a custom time (in seconds).
Beware that this affects the IBC relayer and will freeze the clients if your Pond is stopped for a longer than the provided time.
pond init --unbonding-time 300
Pond uses the cosmos.directory proxy to get data from public API/RPC nodes. Override them with:
pond init --api-url https://my.api.node
pond init --rpc-url https://my.rpc.node
In case you need a custom Kujira version, you can use a local kujirad binary. The log output is written to $HOME/.pond/kujira1-<N>/kujirad.log
pond init --binary /path/to/my/kujirad
You can override default genesis parameters by providing a json file containing all the needed changes.
pond init --overrides custom-settings.json
custom-settings.json:
{
"app_state": {
"oracle": {
"params": {
"required_denoms": [
"FOO",
"BAR"
]
}
}
}
}
Start your Pond
pond start
Stop your Pond
pond stop
Retrieve infrastructure information
List all accounts and their addresses
$ pond info accounts
chain name address
kujira deployer kujira1k3g54c2sc7g9mgzuzaukm9pvuzcjqy92nk9wse
kujira relayer kujira1egssdw6et0pwdcdzl4nvyck68g3qcru99ynkjr
kujira test0 kujira1cyyzpxplxdzkeea7kwsydadg87357qnaww84dg
kujira test1 kujira18s5lynnmx37hq4wlrw9gdn68sg2uxp5r39mjh5
List the seed phrase of a specific account
$ pond info seed test0
notice oak worry limit wrap speak medal online prefer cluster roof addict wrist behave treat actual wasp year salad speed social layer crew genius
List all deployed code ids and associated names
$ pond info codes
id checksum name
1 418CF9A2…B2DFAA22 kujira_bow_xyk
2 715934C4…49E9A7E9 kujira_bow_lsd
3 F3B81230…9ABCC502 kujira_bow_stable
4 98CC2EDA…CFF50C5F kujira_stable_mint
5 8A6FA03E…BD42C198 kujira_fin
List all deployed contracts by code id
$ pond info contracts
id address label
1 kujira1e8rl4aawc44c2kqrx6urxktsf9h8k9sg9yufaxgegge2sn85vx7sdek0cz Bow ETH-USK
1 kujira1narj7rjhmth6hzk8rmd3sqeus293tpj7r35n0dlm6lgle6zuevusl43a5j Bow KUJI-USK
2 kujira1xfm4hyctm8zxjtjw7lsvtewnks36pekzt4x9fjjvhm8tr23vj42qp8m3au USK Controller
3 kujira1gze5anmdc34plj9vaku3mn2cdurhd6r2680fr2xhvdcp32jzwl4q4t752w Fin ETH-USK
3 kujira1nc8c8zktapz5y25jqfw4dlu8u0z0m2j5lhv4djrahvtr2dgekceqww683c Fin KUJI-USK
3 kujira1ttcd5lk9xw2kenzxh7060h8ehyklqp5rx92j9p0ux36vsjhhrx9qmqr896 Fin USDC-USK
3 kujira17gr3fgpwes8q8y0gt6rqjnqwe7p4dpel85nu57epedujdmuhug7sexs9fd Fin stETH-ETH
4 kujira1pz4z5kakz60z738ghu4v8sc6qumuxcrezxafqhmzh77lw88y0vmqhu03uz Bow stETH-ETH
5 kujira1yzd7hwez9yntpc3z34qcx5c7gduw65qk92a88u2pgpw0cxgdq7lsleea3r Bow USDC-USK
List all chain and node specific URLs
$ pond info urls
kujira1-1
api http://127.0.0.1:11117
rpc http://127.0.0.1:11157
grpc http://127.0.0.1:11190
feeder http://127.0.0.1:11171/api/v1/prices
Do Transaction on any of your chains. It will send the transaction to kujira-1
if no --chain-id
is provided.
pond tx ibc-transfer transfer transfer channel-0 cosmos18s5lynnmx37hq4wlrw9gdn68sg2uxp5rqde267 123456789ukuji --from test0
Query any of your chains. It will query kujira-1
by default if you don't provide a --chain-id
.
$ pond q bank balances cosmos18s5lynnmx37hq4wlrw9gdn68sg2uxp5rqde267 --chain-id cosmoshub-1
balances:
- amount: "123456789"
denom: ibc/90F27756D300141BDF07B83E65401BDC58C05269B9BAE3ECB0B20FAB166BCF8F
- amount: "1000000000000"
denom: uatom
pagination:
next_key: null
total: "0"
Upgrade provides an easy way to test chain upgrades. For this to work, Pond creates an upgrade proposal, waits for the upgrade height and then restarts using the new binary.
--binary
mode
pond upgrade --version v1.2.3 --binary /path/to/kujirad
Submit a gov proposal and optionally let all validators vote with the specified option.
pond gov submit-proposal my-proposal.json
pond gov submit-proposal my-proposal.json --vote yes
Deploy local wasm binaries or execute plan files (a way to automate contract deployments)
pond deploy myapp.wasm
pond deploy myplan.json
For the plan deployment to work, Pond stores the required wasm code information in the code registry and maps it to a human readable name which is needed in the plan files.
It ships with a default registry, containing most of the Kujira core apps and can be managed by using pond registry
commands or editing $HOME/.pond/registry.json
manually.
Every binary that is deployed via pond deploy
will automatically added to the registry and referenced to its basename, so it can immediately be used for plan file deployments.
Update the registry entry, in case the name or location of a code has changed
pond registry update myapp.wasm --name myapp --source file:///tmp/myapp.wasm
In case you want to set up a new pond or apply your plan file on a different Pond, you can export your current registry and import it again
pond export /tmp/myregistry.json
pond import /tmp/myregistry.json
This downloads and deploys the code with the given code id from Kujira mainnet
{
"mycode": {
"source": "kaiyo-1://12345"
}
}
This deploys locally stored code
{
"mycode": {
"source": "file:///tmp/12345.wasm"
}
}
To make complex smart contract deployments easy to maintain, Pond offers the possibility to describe the order and parameters of your contract deployments and required denoms in json files and execute them. Pond then takes care of the creation of needed denoms and wasm code deployments as well as the instantiation of the contracts and needed contract executions. It keeps track all items and lets you access certain properties like contract address or denom path in every subsequent deployment via a simple template string (see "Planfile Syntax" for explanation).
Default plan files shipped with pond can be found in $HOME/.pond/planfiles
.
{
"denom": "{{ .Denoms.USDC.Path }}",
"address": "{{ .Contracts.my_contract.Address }}",
"code_id": "{{ .CodeIds.my_contract }} | int"
}
Note: To be able to use the resulting code id as an integer value, you need to add | int
after the template string. Otherwise the code id is provided as a string.
All deployments are done from the deployer
account: kujira1k3g54c2sc7g9mgzuzaukm9pvuzcjqy92nk9wse
Plan files are simple json files that describe denoms and contract instantiations. They are designed to be as simple as possible and use the same instantiation message like the one that is used when executing it manually via kujirad wasm execute
.
Pond creates denoms that have a provided nonce
as factory/kujira1k3g54c2sc7g9mgzuzaukm9pvuzcjqy92nk9wse/{nonce}
from the deployer
account. If mint
is provided, it will also mint the specified amount of tokens into each test*
account. All denoms with a provided path
will be skipped.
Example:
{
"denoms": [
{
"name": "KUJI",
"path": "ukuji"
},
{
"name": "USDC",
"nonce": "ibc/FE98AA...9576A9"
},
{
"name": "POND",
"nonce": "upond",
"mint": "10_000_000"
},
]
}
The above example will create the POND
token as factory/kujira1k3g54c2sc7g9mgzuzaukm9pvuzcjqy92nk9wse/upond
and mint 10 POND
(10m upond) into each test wallet. KUJI
and USDC
have a path provided and therefore will be skipped.
It stores the path of all three denoms, which can be accessed in subsequent contract instantiations of that deployment via {{ .Denoms.POND.Address }}
for example.
If you are working on contracts that change a lot during the development, updating the registry all the might become a tedious task. Therefore you can specify your sources directly in the plan file and Pond deploys them and updates the registry accordingly.
{
"codes":
"my_project": "file:///path/to/my_project/artifacts/my_project-aarch64.wasm"
}
Pond instantiates all contracts from the deployer
account.
To speed up the deployments, Pond handles contracts in batches which combine all instantiations into a single transaction:
{
"contracts": [
[
{"name": "contract1", "msg": {}},
{"name": "contract2", "msg": {}}
],
[
{"name": "contract3", "msg": {}}
]
]
}
The above example executes two batches. The first creating contract1 and contract2 in one transaction, the second creating contract3.
This way you speed up the deployment by maintaing a specific order of instantiations, if needed.
The name of your contract inside the plan file deployment run. This is needed to be able to refer to the contract in later instantiations.
The name of the wasm code stored in the registry. Pond will deploy the code, if it hasn't been yet.
A label for the newly created contract.
The instantiation message needed to create the new contract.
Some contracts need to be provided some amount of funds when they are created.
Some contracts create tokens on their instantiation. To be able for Pond to make them usable in further steps, it needs to know their names.
You can specify /cosmwasm.wasm.v1.MsgExecuteContract
messages that are triggered after the contract is instantiated. This is useful, if you need to grant permissions for the newly created contract to a different contract for example.
The following example is a part of the kujira
plan file, that is shipped and applied by default on the first start of each Pond instance (can be disabled with --no-contracts
). It should showcase the use of the deployment order and templating.
{
"denoms": [
{
"name": "KUJI",
"path": "ukuji"
}
],
"contracts": [
[
{
"name": "kujira_stable_mint_usk",
"code": "kujira_stable_mint",
"label": "USK Controller",
"funds": "10000000ukuji",
"msg": {
"denom": "uusk"
},
"creates": [
{
"name": "USK",
"nonce": "uusk"
}
]
}
],
[
{
"name": "kujira_fin_kuji_usk",
"code": "kujira_fin",
"label": "Fin KUJI-USK",
"msg": {
"denoms": [
{
"native": "{{ .Denoms.KUJI.Path }}"
},
{
"native": "{{ .Denoms.USK.Path }}"
}
],
"price_precision": {
"decimal_places": 4
},
"decimal_delta": 0,
"fee_taker": "0.0015",
"fee_maker": "0.00075"
}
}
],
[
{
"name": "kujira_bow_kuji_usk",
"code": "kujira_bow_xyk",
"label": "Bow KUJI-USK",
"funds": "10000000ukuji",
"msg": {
"fin_contract": "{{ .Contracts.kujira_fin_kuji_usk.Address }}",
"intervals": [
"0.01",
"0.05"
],
"fee": "0.1",
"amp": "1"
}
}
]
]
}
In the above example plan file, Pond will at first check if it can find the referenced wasm codes in the code registry and deploy them if can't find them on-chain.
Next, it will create all tokens that have a provided nonce
but no path
. In this example, it crates no denom, because KUJI is provided with a path
.
Now that all codes are deployed and needed denoms are created, it instantiates the "USK Controller". That will instantly create the USK token and therefore needs some initial funds
. To be able to refer to the newly created USK address later, Pond retrieves and stores the path of all assets listed in the creates
section.
It then instantiates a KUJI/USK Fin market and uses the retrieved path from the USK token, created before.
Last but not least it creates a Bow pool by referencing to the KUJI/USK Fin market via its name: kujira_fin_kuji_usk
.