Skip to content

Commit

Permalink
bitsong fantoken factory support
Browse files Browse the repository at this point in the history
  • Loading branch information
NoahSaso committed Jul 8, 2024
1 parent 4c91c99 commit fb631bb
Show file tree
Hide file tree
Showing 37 changed files with 2,961 additions and 685 deletions.
1 change: 1 addition & 0 deletions packages/dispatch/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"prettier": "@dao-dao/config/prettier",
"dependencies": {
"@cosmjs/cosmwasm-stargate": "^0.32.3",
"@cosmjs/crypto": "^0.32.3",
"@cosmjs/proto-signing": "^0.32.3"
}
}
229 changes: 150 additions & 79 deletions packages/dispatch/scripts/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import fs from 'fs'
import path from 'path'

import { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate'
import { stringToPath as stringToHdPath } from '@cosmjs/crypto'
import { DirectSecp256k1HdWallet, EncodeObject } from '@cosmjs/proto-signing'
import chalk from 'chalk'
import { Command } from 'commander'
Expand All @@ -11,40 +12,55 @@ import {
chainQueries,
makeGetSignerOptions,
makeReactQueryClient,
skipQueries,
} from '@dao-dao/state'
import { SupportedChainConfig, cwMsgToEncodeObject } from '@dao-dao/types'
import {
ContractVersion,
SupportedChainConfig,
cwMsgToEncodeObject,
} from '@dao-dao/types'
import { MsgExec } from '@dao-dao/types/protobuf/codegen/cosmos/authz/v1beta1/tx'
import { MsgStoreCode } from '@dao-dao/types/protobuf/codegen/cosmwasm/wasm/v1/tx'
import { AccessType } from '@dao-dao/types/protobuf/codegen/cosmwasm/wasm/v1/types'
import {
CHAIN_GAS_MULTIPLIER,
encodeJsonToBase64,
findEventsAttributeValue,
getChainForChainId,
getRpcForChainId,
gzipCompress,
maybeGetChainForChainId,
} from '@dao-dao/utils'

const { log } = console

const { parsed: { MNEMONIC, DAO_CONTRACTS_DIR, POLYTONE_CONTRACTS_DIR } = {} } =
dotenv.config()

if (!MNEMONIC) {
console.error('MNEMONIC not set')
log(chalk.red('MNEMONIC not set'))
process.exit(1)
}
if (!DAO_CONTRACTS_DIR) {
console.error('DAO_CONTRACTS_DIR not set')
log(chalk.red('DAO_CONTRACTS_DIR not set'))
process.exit(1)
}
if (!POLYTONE_CONTRACTS_DIR) {
console.error('POLYTONE_CONTRACTS_DIR not set')
log(chalk.red('POLYTONE_CONTRACTS_DIR not set'))
process.exit(1)
}

enum Mode {
Dao = 'dao',
Polytone = 'polytone',
Factory = 'factory',
}

const program = new Command()
program.requiredOption('-c, --chain <ID>', 'chain ID')
program.option('-p, --polytone', 'only deploy polytone contracts')
program.option(
'-m, --mode <mode>',
'deploy mode (dao = deploy DAO contracts and instantiate admin factory, polytone = deploy Polytone contracts, factory = instantiate admin factory)',
'dao'
)
program.option(
'-a, --authz <granter>',
'upload contracts via authz exec as this granter'
Expand All @@ -55,32 +71,36 @@ program.option(
)

program.parse(process.argv)
const { chain: chainId, polytone, authz, exclude: _exclude } = program.opts()
const { chain: chainId, mode, authz, exclude: _exclude } = program.opts()

const exclude: string[] | undefined = _exclude?.split(',')

const { log } = console
if (!Object.values(Mode).includes(mode)) {
log(
chalk.red('Invalid mode. Must be one of: ' + Object.values(Mode).join(', '))
)
process.exit(1)
}

const codeIdMap: Record<string, number | undefined> = {}

const main = async () => {
const queryClient = await makeReactQueryClient()

const chain =
maybeGetChainForChainId(chainId) ||
// Fetch from Skip API if doesn't exist locally.
(await queryClient.fetchQuery(
skipQueries.chain(queryClient, {
chainId,
})
))
const chainName = chain.chain_name
const bech32Prefix = chain.bech32_prefix
const {
chain_name: chainName,
bech32_prefix: bech32Prefix,
network_type: networkType,
slip44,
} = getChainForChainId(chainId)

await queryClient.prefetchQuery(
chainQueries.dynamicGasPrice({ chainId: chainId })
)

const signer = await DirectSecp256k1HdWallet.fromMnemonic(MNEMONIC, {
prefix: bech32Prefix,
hdPaths: [stringToHdPath(`m/44'/${slip44}'/0'/0/0`)],
})
const sender = (await signer.getAccounts())[0].address

Expand Down Expand Up @@ -230,33 +250,39 @@ const main = async () => {
label: string
prefixLength: number
}) => {
const { events, transactionHash } = await client.signAndBroadcast(
sender,
[
cwMsgToEncodeObject(
chainId,
{
wasm: {
instantiate: {
code_id: codeId,
msg: encodeJsonToBase64(msg),
funds: [],
label,
admin: undefined,
let transactionHash
try {
transactionHash = await client.signAndBroadcastSync(
sender,
[
cwMsgToEncodeObject(
chainId,
{
wasm: {
instantiate: {
code_id: codeId,
msg: encodeJsonToBase64(msg),
funds: [],
label,
admin: undefined,
},
},
},
},
sender
),
],
CHAIN_GAS_MULTIPLIER
)

const contractAddress = findEventsAttributeValue(
events,
'instantiate',
'_contract_address'
)
sender
),
],
CHAIN_GAS_MULTIPLIER
)
} catch (err) {
log(
chalk.red(
`[${id}.CONTRACT]${' '.repeat(
prefixLength - id.length - 11
)}instantiate failed`
)
)
throw err
}

log(
chalk.greenBright(
Expand All @@ -266,6 +292,38 @@ const main = async () => {
)
)

// Poll for TX.
let events
let tries = 15
while (tries > 0) {
try {
events = (await client.getTx(transactionHash))?.events
if (events) {
break
}
} catch {}

tries--
await new Promise((resolve) => setTimeout(resolve, 1000))
}

if (!events) {
log(
chalk.red(
`[${id}.CONTRACT]${' '.repeat(
prefixLength - id.length - 11
)}TX not found`
)
)
process.exit(1)
}

const contractAddress = findEventsAttributeValue(
events,
'instantiate',
'_contract_address'
)

if (!contractAddress) {
log(
chalk.red(
Expand All @@ -291,7 +349,7 @@ const main = async () => {
log()

// Upload polytone contracts only.
if (polytone) {
if (mode === Mode.Polytone) {
const contracts = [
'polytone_listener',
'polytone_note',
Expand All @@ -313,44 +371,59 @@ const main = async () => {
process.exit(0)
}

let consolePrefixLength = 32

// Upload DAO contracts.
if (mode === Mode.Dao) {
// List files in the contracts directory.
const contracts = fs
.readdirSync(DAO_CONTRACTS_DIR)
.filter((file) => file.endsWith('.wasm'))
.sort()

// List files in the contracts directory.
const contracts = fs
.readdirSync(DAO_CONTRACTS_DIR)
.filter((file) => file.endsWith('.wasm'))
.sort()
// Set console prefix length to the max file length plus space for brackets
// and longest ID suffix (CONTRACT).
consolePrefixLength = Math.max(...contracts.map((file) => file.length)) + 10

// Set console prefix length to the max file length plus space for brackets
// and longest ID suffix (CONTRACT).
const consolePrefixLength =
Math.max(...contracts.map((file) => file.length)) + 10
for (const contract of contracts) {
const id = contract.slice(0, -5)
if (exclude?.some((substring) => id.includes(substring))) {
continue
}

const codeIdMap: Record<string, number | undefined> = {}
const file = path.join(DAO_CONTRACTS_DIR, contract)

for (const contract of contracts) {
const id = contract.slice(0, -5)
if (exclude?.some((substring) => id.includes(substring))) {
continue
if (!(id in codeIdMap)) {
codeIdMap[id] = await uploadContract({
id,
file,
prefixLength: consolePrefixLength,
})
} else {
log(
chalk.green(
`[${id}.CODE_ID]${' '.repeat(
consolePrefixLength - id.length - 10
)}${codeIdMap[id]}`
)
)
}
}
}

const file = path.join(DAO_CONTRACTS_DIR, contract)

if (!(id in codeIdMap)) {
codeIdMap[id] = await uploadContract({
id,
file,
prefixLength: consolePrefixLength,
})
} else {
log(
chalk.green(
`[${id}.CODE_ID]${' '.repeat(consolePrefixLength - id.length - 10)}${
codeIdMap[id]
}`
)
)
// Upload just admin factory if needed.
else if (mode === Mode.Factory && !codeIdMap['cw_admin_factory']) {
const file = path.join(DAO_CONTRACTS_DIR, 'cw_admin_factory.wasm')
if (!fs.existsSync(file)) {
log(chalk.red('cw_admin_factory.wasm not found'))
process.exit(1)
}

codeIdMap['cw_admin_factory'] = await uploadContract({
id: 'cw_admin_factory',
file,
prefixLength: consolePrefixLength,
})
}

// Instantiate admin factory.
Expand All @@ -374,10 +447,7 @@ const main = async () => {
const config: SupportedChainConfig = {
chainId,
name: chainName,
mainnet:
'is_testnet' in chain
? !chain.is_testnet
: chain.network_type === 'mainnet',
mainnet: networkType === 'mainnet',
accentColor: 'ACCENT_COLOR',
factoryContractAddress: adminFactoryAddress,
explorerUrlTemplates: {
Expand All @@ -386,6 +456,7 @@ const main = async () => {
govProp: `https://ping.pub/${chainName}/gov/REPLACE`,
wallet: `https://ping.pub/${chainName}/account/REPLACE`,
},
codeIdsVersion: ContractVersion.Unknown,
codeIds: {
Cw1Whitelist: codeIdMap['cw1_whitelist'] ?? -1,
Cw4Group: codeIdMap['cw4_group'] ?? -1,
Expand Down
10 changes: 10 additions & 0 deletions packages/state/recoil/selectors/chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import { Params as NobleTariffParams } from '@dao-dao/types/protobuf/codegen/tar
import {
MAINNET,
SecretCosmWasmClient,
bitsongProtoRpcClientRouter,
cosmosProtoRpcClientRouter,
cosmosSdkVersionIs46OrHigher,
cosmosSdkVersionIs47OrHigher,
Expand Down Expand Up @@ -394,6 +395,15 @@ export const tokenFactoryDenomCreationFeeSelector = selectorFamily<
return params?.creationFee
}

if (
chainId === ChainId.BitsongMainnet ||
chainId === ChainId.BitsongTestnet
) {
const bitsongClient = await bitsongProtoRpcClientRouter.connect(chainId)
const { params } = await bitsongClient.fantoken.v1beta1.params()
return params?.issueFee && [params.issueFee]
}

const osmosisClient = get(osmosisRpcClientForChainSelector(chainId))
try {
return (await osmosisClient.tokenfactory.v1beta1.params()).params
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,14 +110,12 @@ export class TokenStakedVotingModule extends VotingModuleBase<CwDao> {
}
: {
factory: encodeJsonToBase64({
wasm: {
execute: {
contract_addr: config.token.factory.address,
funds: config.token.factory.funds || [],
msg: encodeJsonToBase64(config.token.factory.message),
},
} as WasmMsg,
}),
execute: {
contract_addr: config.token.factory.address,
funds: config.token.factory.funds || [],
msg: encodeJsonToBase64(config.token.factory.message),
},
} as WasmMsg),
},
unstaking_duration: config.unstakingDuration,
} as InstantiateMsg),
Expand Down
Loading

0 comments on commit fb631bb

Please sign in to comment.