Compare commits

...

26 Commits

Author SHA1 Message Date
7490e24a1d Update scripts/request-app-deployment.sh
All checks were successful
Publish ApplicationRecord to Registry / cns_publish (push) Successful in 1m26s
2024-06-25 16:06:14 +00:00
da62b2fbf3 Update scripts/request-app-deployment.sh
Some checks failed
Publish ApplicationRecord to Registry / cns_publish (push) Has been cancelled
2024-06-25 16:05:59 +00:00
8a08acf250 Update scripts/request-app-deployment.sh
All checks were successful
Publish ApplicationRecord to Registry / cns_publish (push) Successful in 1m16s
2024-06-25 16:00:19 +00:00
6c6ee08024 increase CERC_MAX_GENERATE_TIME
All checks were successful
Publish ApplicationRecord to Registry / cns_publish (push) Successful in 1m19s
2024-06-25 15:35:11 +00:00
e6f56c0509 Add .env
All checks were successful
Publish ApplicationRecord to Registry / cns_publish (push) Successful in 1m20s
2024-06-25 15:33:18 +00:00
50489c00cd ffs
All checks were successful
Publish ApplicationRecord to Registry / cns_publish (push) Successful in 1m20s
2024-06-25 15:10:05 +00:00
ac5a7f2cb6 Update package.json
All checks were successful
Publish ApplicationRecord to Registry / cns_publish (push) Successful in 1m24s
2024-06-25 15:07:12 +00:00
04397853d9 set name
All checks were successful
Publish ApplicationRecord to Registry / cns_publish (push) Successful in 1m23s
2024-06-25 15:01:36 +00:00
zramsay
2ab4cb9349 test
Some checks failed
Publish ApplicationRecord to Registry / cns_publish (push) Failing after 1m3s
2024-06-25 10:36:00 -04:00
Serkan Reis
ea7dea6a2a
Merge pull request #391 from public-awesome/collection-creation-summary
Update parser for createVendingMinter transaction result
2024-06-17 22:18:16 +03:00
Serkan Reis
ed9105684c Update parser for createVendingMinter transaction result 2024-06-17 22:17:04 +03:00
Serkan Reis
3511a57eb9 Use hardcoded fees for editing badges 2024-06-11 20:51:55 +03:00
Serkan Reis
28741049ee Remove testnet checks for contract upload 2024-06-09 16:05:30 +03:00
Serkan Reis
1003fcf4ae Contract Upload UI update 2024-06-09 16:02:53 +03:00
Serkan Reis
a96c80462d
Merge pull request #386 from public-awesome/contract-upload-authorization
Enable contract uploads with authorization
2024-06-09 15:52:19 +03:00
Serkan Reis
d889e7e04b Enable contract uploads with authorization 2024-06-09 15:45:28 +03:00
Serkan Reis
be93200f53
Merge pull request #384 from public-awesome/handle-non-stars-creation-fees
Handle non-STARS collection creation fees
2024-05-28 13:39:26 +03:00
Serkan Reis
3bbed658a7 Handle non-STARS creation fees for open/limited edition minter 2024-05-22 21:02:12 +03:00
Serkan Reis
fa1475f109 Handle non-STARS creation fees for vending & base minter 2024-05-22 20:25:41 +03:00
Serkan Reis
d1b5041312
Merge pull request #382 from public-awesome/oe-wl-on-collection-list
Add OE/LE whitelist info to the collection list
2024-05-09 16:34:53 +03:00
Serkan Reis
0958b0db94 Add WL info for OE collections on the collection list 2024-05-09 16:28:10 +03:00
Serkan Reis
0354131ad1
Merge pull request #380 from public-awesome/cosmos-kit-version-update
Update cosmos-kit package versions
2024-05-08 20:04:46 +03:00
Serkan Reis
f7880540ad Update cosmjs package versions 2024-05-08 19:57:36 +03:00
Serkan Reis
123e07362d Update versions for cosmos-kit packages 2024-05-08 19:22:23 +03:00
Serkan Reis
aaf7b82b43
Merge pull request #378 from public-awesome/cancel-auction
Add cancel auction UI
2024-05-06 17:06:25 +03:00
Serkan Reis
467c7a4cfb Add cancel auction UI 2024-05-06 17:05:40 +03:00
15 changed files with 21570 additions and 1073 deletions

1
.env Normal file
View File

@ -0,0 +1 @@
CERC_MAX_GENERATE_TIME=180

45
.github/workflows/publish.yaml vendored Normal file
View File

@ -0,0 +1,45 @@
name: Publish ApplicationRecord to Registry
on:
release:
types: [published]
push:
branches:
- main
- '*'
env:
CERC_REGISTRY_USER_KEY: ${{ secrets.CICD_LACONIC_USER_KEY }}
CERC_REGISTRY_BOND_ID: ${{ secrets.CICD_LACONIC_BOND_ID }}
jobs:
cns_publish:
runs-on: ubuntu-latest
steps:
- name: "Clone project repository"
uses: actions/checkout@v3
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: 18 # though you need version 14 with geojson
# - name: "Install exiftool"
# run: |
# apt-get update -y
# apt-get upgrade -y
# apt-get install exiftool -y
#- name: "Exiftool Version"
# run: |
# exiftool -ver
- name: "Install Yarn"
run: npm install -g yarn
- name: "Install registry CLI"
run: |
npm config set @cerc-io:registry https://git.vdb.to/api/packages/cerc-io/npm/
yarn global add @cerc-io/laconic-registry-cli
- name: "Install jq"
uses: dcarbone/install-jq-action@v2.1.0
- name: "Publish App Record"
run: scripts/publish-app-record.sh
#- name: "Create Metadata Record"
# run: scripts/create-metadata-record.sh
- name: "Request Deployment"
run: scripts/request-app-deployment.sh

View File

@ -298,17 +298,16 @@ export const Sidebar = () => {
>
<Link href="/contracts/royaltyRegistry/">Royalty Registry</Link>
</li>
<Conditional test={NETWORK === 'testnet'}>
<li
className={clsx(
'text-lg font-bold hover:text-white hover:bg-stargaze-80 rounded',
router.asPath.includes('/contracts/upload/') ? 'text-white' : 'text-gray',
)}
tabIndex={-1}
>
<Link href="/contracts/upload/">Upload Contract</Link>
</li>
</Conditional>
<li
className={clsx(
'text-lg font-bold hover:text-white hover:bg-stargaze-80 rounded',
router.asPath.includes('/contracts/upload/') ? 'text-white' : 'text-gray',
)}
tabIndex={-1}
>
<Link href="/contracts/upload/">Upload Contract</Link>
</li>
</ul>
</li>
</ul>

View File

@ -5,6 +5,7 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import { toUtf8 } from '@cosmjs/encoding'
import type { Coin } from '@cosmjs/proto-signing'
import { coin } from '@cosmjs/proto-signing'
import axios from 'axios'
import clsx from 'clsx'
@ -13,7 +14,7 @@ import type { MinterType } from 'components/collections/actions/Combobox'
import { Conditional } from 'components/Conditional'
import { ConfirmationModal } from 'components/ConfirmationModal'
import { LoadingModal } from 'components/LoadingModal'
import { type TokenInfo } from 'config/token'
import { type TokenInfo, tokensList } from 'config/token'
import { useContracts } from 'contexts/contracts'
import { addLogItem } from 'contexts/log'
import type { DispatchExecuteArgs as OpenEditionFactoryDispatchExecuteArgs } from 'contracts/openEditionFactory/messages/execute'
@ -73,7 +74,7 @@ export interface OpenEditionMinterDetailsDataProps {
interface OpenEditionMinterCreatorProps {
onChange: (data: OpenEditionMinterCreatorDataProps) => void
onDetailsChange: (data: OpenEditionMinterDetailsDataProps) => void
openEditionMinterCreationFee?: string
openEditionMinterCreationFee?: Coin
minimumMintPrice?: string
minterType?: MinterType
mintTokenFromFactory?: TokenInfo | undefined
@ -480,20 +481,45 @@ export const OpenEditionMinterCreator = ({
const checkwalletBalance = async () => {
if (!wallet.isWalletConnected) throw new Error('Wallet not connected.')
let amountNeeded = 0
if (whitelistDetails?.whitelistState === 'new' && whitelistDetails.memberLimit) {
amountNeeded =
Math.ceil(Number(whitelistDetails.memberLimit) / 1000) * 100000000 + Number(openEditionMinterCreationFee)
} else {
amountNeeded = openEditionMinterCreationFee ? Number(openEditionMinterCreationFee) : 0
}
await (await wallet.getCosmWasmClient()).getBalance(wallet.address || '', 'ustars').then((balance) => {
if (amountNeeded >= Number(balance.amount))
throw new Error(
`Insufficient wallet balance to instantiate the required contracts. Needed amount: ${(
amountNeeded / 1000000
).toString()} STARS`,
)
const queryClient = await wallet.getCosmWasmClient()
const creationFeeDenom = tokensList.find((token) => token.denom === openEditionMinterCreationFee?.denom)
await queryClient.getBalance(wallet.address || '', 'ustars').then(async (starsBalance) => {
await queryClient
.getBalance(wallet.address || '', openEditionMinterCreationFee?.denom as string)
.then((creationFeeDenomBalance) => {
if (whitelistDetails?.whitelistState === 'new' && whitelistDetails.memberLimit) {
const whitelistCreationFee = Math.ceil(Number(whitelistDetails.memberLimit) / 1000) * 100000000
if (openEditionMinterCreationFee?.denom === 'ustars') {
const amountNeeded = whitelistCreationFee + Number(openEditionMinterCreationFee.amount)
if (amountNeeded >= Number(starsBalance.amount))
throw new Error(
`Insufficient wallet balance to instantiate the required contracts. Needed amount: ${(
amountNeeded / 1000000
).toString()} STARS`,
)
} else {
if (whitelistCreationFee >= Number(starsBalance.amount))
throw new Error(
`Insufficient wallet balance to instantiate the whitelist. Needed amount: ${(
whitelistCreationFee / 1000000
).toString()} STARS`,
)
if (Number(openEditionMinterCreationFee?.amount) > Number(creationFeeDenomBalance.amount))
throw new Error(
`Insufficient wallet balance to instantiate the required contracts. Needed amount: ${(
Number(openEditionMinterCreationFee?.amount) / 1000000
).toString()} ${
creationFeeDenom ? creationFeeDenom.displayName : openEditionMinterCreationFee?.denom
}`,
)
}
} else if (Number(openEditionMinterCreationFee?.amount) > Number(creationFeeDenomBalance.amount))
throw new Error(
`Insufficient wallet balance to instantiate the required contracts. Needed amount: ${(
Number(openEditionMinterCreationFee?.amount) / 1000000
).toString()} ${creationFeeDenom ? creationFeeDenom.displayName : openEditionMinterCreationFee?.denom}`,
)
})
})
}
@ -899,7 +925,7 @@ export const OpenEditionMinterCreator = ({
messages: openEditionFactoryMessages,
txSigner: wallet.address || '',
msg,
funds: [coin(openEditionMinterCreationFee as string, 'ustars')],
funds: [openEditionMinterCreationFee as Coin],
updatable: collectionDetails?.updatable,
}
await openEditionFactoryDispatchExecute(payload)

View File

@ -342,7 +342,8 @@ export const badgeHub = (client: SigningCosmWasmClient, txSigner: string): Badge
},
'auto',
'',
editFee ? [coin(editFee, 'ustars')] : [],
[coin(200000000, 'ustars')],
// editFee ? [coin(editFee, 'ustars')] : [],
)
return res.transactionHash

View File

@ -63,8 +63,10 @@ export const vendingFactory = (client: SigningCosmWasmClient, txSigner: string):
const result = await client.execute(senderAddress, contractAddress, msg, 'auto', '', funds)
return {
vendingMinterAddress: result.logs[0].events[16].attributes[0].value,
sg721Address: result.logs[0].events[18].attributes[0].value,
vendingMinterAddress: result.logs[0].events.filter((e) => e.type === 'instantiate')[0].attributes[0].value,
sg721Address: result.logs[0].events
.filter((e) => e.type === 'wasm')
.filter((e) => e.attributes[2]?.key === 'sg721_address')[0].attributes[2].value,
transactionHash: result.transactionHash,
logs: result.logs,
}

18257
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,7 @@
{
"name": "stargaze-studio",
"private": true,
"name": "@mito/stargaze-studio",
"repository": "https://git.vdb.to/LaconicNetwork/stargaze-studio",
"version": "0.8.7",
"workspaces": [
"packages/*"
@ -13,21 +15,21 @@
},
"dependencies": {
"@aws-sdk/client-s3": "^3",
"@cosmjs/cosmwasm-stargate": "0.32.2",
"@cosmjs/encoding": "0.32.2",
"@cosmjs/math": "0.32.2",
"@cosmjs/proto-signing": "0.32.2",
"@cosmjs/stargate": "0.32.2",
"cosmjs-types": "0.9.0",
"@cosmos-kit/keplr": "^2.4.4",
"@cosmos-kit/leap": "^2.4.3",
"@cosmos-kit/leap-metamask-cosmos-snap": "^0.3.3",
"@cosmos-kit/react": "^2.9.3",
"crypto-js": "4.1.1",
"@types/crypto-js": "4.2.1",
"@cosmjs/cosmwasm-stargate": "0.32.3",
"@cosmjs/encoding": "0.32.3",
"@cosmjs/math": "0.32.3",
"@cosmjs/proto-signing": "0.32.3",
"@cosmjs/stargate": "0.32.3",
"@cosmos-kit/keplr": "2.8.0",
"@cosmos-kit/leap": "2.8.0",
"@cosmos-kit/leap-metamask-cosmos-snap": "0.8.0",
"@cosmos-kit/react": "2.12.0",
"@fontsource/jetbrains-mono": "^4",
"@fontsource/roboto": "^4",
"merkletreejs": "0.3.11",
"@headlessui/react": "1.6.0",
"@headlessui/tailwindcss": "0.2.0",
"@heroicons/react": "2.0.18",
"@interchain-ui/react": "1.23.11",
"@leapwallet/cosmos-snap-provider": "0.1.24",
"@pinata/sdk": "^1.1.26",
"@popperjs/core": "^2",
@ -35,20 +37,23 @@
"@tailwindcss/forms": "^0",
"@tailwindcss/line-clamp": "^0",
"@typeform/embed-react": "2.21.0",
"@types/crypto-js": "4.2.1",
"@types/pako": "^2.0.3",
"axios": "^0",
"chain-registry": "^1.20.0",
"clsx": "^1",
"compare-versions": "^4",
"cosmjs-types": "0.9.0",
"crypto-js": "4.1.1",
"daisyui": "^2.19.0",
"html-to-image": "1.11.11",
"@headlessui/react": "1.6.0",
"@headlessui/tailwindcss": "0.2.0",
"@heroicons/react": "2.0.18",
"jscrypto": "^1.0.3",
"match-sorter": "^6",
"merkletreejs": "0.3.11",
"next": "^12",
"next-seo": "^4",
"nft.storage": "^6.3.0",
"pako": "^2.0.2",
"qrcode.react": "3.1.0",
"react": "^18",
"react-datetime-picker": "^3",
@ -75,8 +80,8 @@
"lint-staged": "^12",
"object-sizeof": "^1.6.0",
"postcss": "^8",
"tailwindcss": "^3",
"tailwind-merge": "1.14.0",
"tailwindcss": "^3",
"typescript": "^4"
},
"eslintConfig": {

View File

@ -0,0 +1,132 @@
/* eslint-disable eslint-comments/disable-enable-pair */
import { Alert } from 'components/Alert'
import { Button } from 'components/Button'
import { Conditional } from 'components/Conditional'
import { ContractPageHeader } from 'components/ContractPageHeader'
import { AddressInput, TextInput } from 'components/forms/FormInput'
import { useInputState } from 'components/forms/FormInput.hooks'
import type { NextPage } from 'next'
import { useRouter } from 'next/router'
import { NextSeo } from 'next-seo'
import { useEffect, useState } from 'react'
import { toast } from 'react-hot-toast'
import { NETWORK } from 'utils/constants'
import { useDebounce } from 'utils/debounce'
import { withMetadata } from 'utils/layout'
import { links } from 'utils/links'
import { resolveAddress } from 'utils/resolveAddress'
import { useWallet } from 'utils/wallet'
const CancelAuctionPage: NextPage = () => {
const wallet = useWallet()
const [isLoading, setIsLoading] = useState(false)
const [txHash, setTxHash] = useState<string | undefined>(undefined)
const collectionAddressState = useInputState({
id: 'collection-address',
name: 'collectionAddress',
title: 'Collection Contract Address',
defaultValue: '',
placeholder: 'stars1...',
})
const collectionAddress = useDebounce(collectionAddressState.value, 300)
const tokenIdState = useInputState({
id: 'token-id',
name: 'tokenId',
title: 'Token ID',
defaultValue: '',
placeholder: '1',
})
const router = useRouter()
useEffect(() => {
if (collectionAddress.length > 0) {
void router.replace({ query: { contractAddress: collectionAddress } })
}
if (collectionAddress.length === 0) {
void router.replace({ query: {} })
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [collectionAddress])
useEffect(() => {
const initial = new URL(document.URL).searchParams.get('contractAddress')
if (initial && initial.length > 0) collectionAddressState.onChange(initial)
}, [])
const resolveCollectionAddress = async () => {
await resolveAddress(collectionAddressState.value.trim(), wallet).then((resolvedAddress) => {
if (resolvedAddress) {
collectionAddressState.onChange(resolvedAddress)
}
})
}
useEffect(() => {
void resolveCollectionAddress()
}, [collectionAddressState.value])
const handleCancelAuction = async () => {
if (!wallet.isWalletConnected) return toast.error('Please connect your wallet.')
if (!collectionAddressState.value) return toast.error('Please enter a collection address.')
const client = await wallet.getSigningCosmWasmClient()
setTxHash(undefined)
setIsLoading(true)
try {
const result = await client.execute(
wallet.address as string,
NETWORK === 'mainnet'
? 'stars1vvdkcn393ddyd47v9g3qv6mvne59d0ykzy9wre3ga0c58dtdg4ksm776jg'
: 'stars1dnadsd7tx0dmnpp26ms7d66zsp7tduygwjgfjzueh0lg9t5lq5vq9kn47c',
{
cancel_auction: {
collection: collectionAddressState.value,
token_id: tokenIdState.value,
},
},
'auto',
)
toast.success('Auction successfully cancelled.')
setTxHash(result.transactionHash)
} catch (error: any) {
toast.error(error.message, { style: { maxWidth: 'none' } })
setTxHash(undefined)
} finally {
setIsLoading(false)
}
}
return (
<section className="py-6 px-12 space-y-4">
<NextSeo title="Cancel Auction" />
<ContractPageHeader link={links.Documentation} title="Cancel Auction" />
<div className="space-y-2">
<AddressInput {...collectionAddressState} />
<TextInput className="w-1/4" {...tokenIdState} />
</div>
<div className="flex flex-row content-center mt-4">
<Button
isDisabled={collectionAddressState.value === ''}
isLoading={isLoading}
onClick={() => {
void handleCancelAuction()
}}
>
Cancel Auction
</Button>
</div>
<Conditional test={txHash !== undefined}>
<Alert type="info">
<b>Transaction Hash:</b> {txHash}
</Alert>
</Conditional>
</section>
)
}
export default withMetadata(CancelAuctionPage, { center: false })

View File

@ -7,6 +7,7 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
import { toUtf8 } from '@cosmjs/encoding'
import type { Coin } from '@cosmjs/proto-signing'
import { coin } from '@cosmjs/proto-signing'
import { Sidetab } from '@typeform/embed-react'
import axios from 'axios'
@ -126,12 +127,12 @@ const CollectionCreationPage: NextPage = () => {
const [royaltyDetails, setRoyaltyDetails] = useState<RoyaltyDetailsDataProps | null>(null)
const [minterType, setMinterType] = useState<MinterType>('vending')
const [vendingMinterCreationFee, setVendingMinterCreationFee] = useState<string | null>(null)
const [baseMinterCreationFee, setBaseMinterCreationFee] = useState<string | null>(null)
const [vendingMinterUpdatableCreationFee, setVendingMinterUpdatableCreationFee] = useState<string | null>(null)
const [openEditionMinterCreationFee, setOpenEditionMinterCreationFee] = useState<string | null>(null)
const [vendingMinterFlexCreationFee, setVendingMinterFlexCreationFee] = useState<string | null>(null)
const [baseMinterUpdatableCreationFee, setBaseMinterUpdatableCreationFee] = useState<string | null>(null)
const [vendingMinterCreationFee, setVendingMinterCreationFee] = useState<Coin | null>(null)
const [baseMinterCreationFee, setBaseMinterCreationFee] = useState<Coin | null>(null)
const [vendingMinterUpdatableCreationFee, setVendingMinterUpdatableCreationFee] = useState<Coin | null>(null)
const [openEditionMinterCreationFee, setOpenEditionMinterCreationFee] = useState<Coin | undefined>(undefined)
const [vendingMinterFlexCreationFee, setVendingMinterFlexCreationFee] = useState<Coin | null>(null)
const [baseMinterUpdatableCreationFee, setBaseMinterUpdatableCreationFee] = useState<Coin | null>(null)
const [minimumMintPrice, setMinimumMintPrice] = useState<string | null>('0')
const [minimumUpdatableMintPrice, setMinimumUpdatableMintPrice] = useState<string | null>('0')
const [minimumOpenEditionMintPrice, setMinimumOpenEditionMintPrice] = useState<string | null>('0')
@ -675,14 +676,11 @@ const CollectionCreationPage: NextPage = () => {
txSigner: wallet.address || '',
msg,
funds: [
coin(
whitelistDetails?.whitelistState !== 'none' && whitelistDetails?.whitelistType === 'flex'
? (vendingMinterFlexCreationFee as string)
: collectionDetails?.updatable
? (vendingMinterUpdatableCreationFee as string)
: (vendingMinterCreationFee as string),
'ustars',
),
whitelistDetails?.whitelistState !== 'none' && whitelistDetails?.whitelistType === 'flex'
? (vendingMinterFlexCreationFee as Coin)
: collectionDetails?.updatable
? (vendingMinterUpdatableCreationFee as Coin)
: (vendingMinterCreationFee as Coin),
],
updatable: collectionDetails?.updatable,
flex: whitelistDetails?.whitelistState !== 'none' && whitelistDetails?.whitelistType === 'flex',
@ -736,10 +734,7 @@ const CollectionCreationPage: NextPage = () => {
txSigner: wallet.address || '',
msg,
funds: [
coin(
collectionDetails?.updatable ? (baseMinterUpdatableCreationFee as string) : (baseMinterCreationFee as string),
'ustars',
),
collectionDetails?.updatable ? (baseMinterUpdatableCreationFee as Coin) : (baseMinterCreationFee as Coin),
],
updatable: collectionDetails?.updatable,
}
@ -1216,7 +1211,7 @@ const CollectionCreationPage: NextPage = () => {
toast.error(`${error.message}`, { style: { maxWidth: 'none' } })
addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() })
})
setBaseMinterCreationFee(baseFactoryParameters?.params?.creation_fee?.amount)
setBaseMinterCreationFee(baseFactoryParameters?.params?.creation_fee)
}
if (BASE_FACTORY_UPDATABLE_ADDRESS) {
const baseFactoryUpdatableParameters = await client
@ -1227,7 +1222,7 @@ const CollectionCreationPage: NextPage = () => {
toast.error(`${error.message}`, { style: { maxWidth: 'none' } })
addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() })
})
setBaseMinterUpdatableCreationFee(baseFactoryUpdatableParameters?.params?.creation_fee?.amount)
setBaseMinterUpdatableCreationFee(baseFactoryUpdatableParameters?.params?.creation_fee)
}
if (VENDING_FACTORY_ADDRESS) {
const vendingFactoryParameters = await client
@ -1236,7 +1231,7 @@ const CollectionCreationPage: NextPage = () => {
toast.error(`${error.message}`, { style: { maxWidth: 'none' } })
addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() })
})
setVendingMinterCreationFee(vendingFactoryParameters?.params?.creation_fee?.amount)
setVendingMinterCreationFee(vendingFactoryParameters?.params?.creation_fee)
setMinimumMintPrice(vendingFactoryParameters?.params?.min_mint_price?.amount)
}
if (VENDING_FACTORY_UPDATABLE_ADDRESS) {
@ -1248,7 +1243,7 @@ const CollectionCreationPage: NextPage = () => {
toast.error(`${error.message}`, { style: { maxWidth: 'none' } })
addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() })
})
setVendingMinterUpdatableCreationFee(vendingFactoryUpdatableParameters?.params?.creation_fee?.amount)
setVendingMinterUpdatableCreationFee(vendingFactoryUpdatableParameters?.params?.creation_fee)
setMinimumUpdatableMintPrice(vendingFactoryUpdatableParameters?.params?.min_mint_price?.amount)
}
if (VENDING_FACTORY_FLEX_ADDRESS) {
@ -1260,7 +1255,7 @@ const CollectionCreationPage: NextPage = () => {
toast.error(`${error.message}`, { style: { maxWidth: 'none' } })
addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() })
})
setVendingMinterFlexCreationFee(vendingFactoryFlexParameters?.params?.creation_fee?.amount)
setVendingMinterFlexCreationFee(vendingFactoryFlexParameters?.params?.creation_fee)
setMinimumFlexMintPrice(vendingFactoryFlexParameters?.params?.min_mint_price?.amount)
}
if (OPEN_EDITION_FACTORY_ADDRESS) {
@ -1270,7 +1265,7 @@ const CollectionCreationPage: NextPage = () => {
toast.error(`${error.message}`, { style: { maxWidth: 'none' } })
addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() })
})
setOpenEditionMinterCreationFee(openEditionFactoryParameters?.params?.creation_fee?.amount)
setOpenEditionMinterCreationFee(openEditionFactoryParameters?.params?.creation_fee)
setMinimumOpenEditionMintPrice(openEditionFactoryParameters?.params?.min_mint_price?.amount)
}
setInitialParametersFetched(true)
@ -1300,7 +1295,7 @@ const CollectionCreationPage: NextPage = () => {
toast.error(`${error.message}`, { style: { maxWidth: 'none' } })
addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() })
})
setOpenEditionMinterCreationFee(openEditionFactoryParameters?.params?.creation_fee?.amount)
setOpenEditionMinterCreationFee(openEditionFactoryParameters?.params?.creation_fee)
setMinimumOpenEditionMintPrice(openEditionFactoryParameters?.params?.min_mint_price?.amount)
setMintTokenFromOpenEditionFactory(
tokensList.find((token) => token.denom === openEditionFactoryParameters?.params?.min_mint_price?.denom),
@ -1347,13 +1342,13 @@ const CollectionCreationPage: NextPage = () => {
})
if (whitelistDetails?.whitelistState !== 'none' && whitelistDetails?.whitelistType === 'flex') {
setVendingMinterFlexCreationFee(vendingFactoryParameters?.params?.creation_fee?.amount)
setVendingMinterFlexCreationFee(vendingFactoryParameters?.params?.creation_fee)
setMinimumFlexMintPrice(vendingFactoryParameters?.params?.min_mint_price?.amount)
} else if (collectionDetails?.updatable) {
setVendingMinterUpdatableCreationFee(vendingFactoryParameters?.params?.creation_fee?.amount)
setVendingMinterUpdatableCreationFee(vendingFactoryParameters?.params?.creation_fee)
setMinimumUpdatableMintPrice(vendingFactoryParameters?.params?.min_mint_price?.amount)
} else {
setVendingMinterCreationFee(vendingFactoryParameters?.params?.creation_fee?.amount)
setVendingMinterCreationFee(vendingFactoryParameters?.params?.creation_fee)
setMinimumMintPrice(vendingFactoryParameters?.params?.min_mint_price?.amount)
}
setMintTokenFromVendingFactory(
@ -1372,53 +1367,82 @@ const CollectionCreationPage: NextPage = () => {
])
const checkwalletBalance = async () => {
await (await wallet.getCosmWasmClient()).getBalance(wallet.address || '', 'ustars').then((balance) => {
if (minterType === 'vending' && whitelistDetails?.whitelistState === 'new') {
if (whitelistDetails.whitelistType !== 'merkletree' && whitelistDetails.memberLimit) {
const amountNeeded =
Math.ceil(Number(whitelistDetails.memberLimit) / 1000) * 100000000 +
(whitelistDetails.whitelistType === 'flex'
? Number(vendingMinterFlexCreationFee)
: collectionDetails?.updatable
? Number(vendingMinterUpdatableCreationFee)
: Number(vendingMinterCreationFee))
if (amountNeeded >= Number(balance.amount))
const queryClient = await wallet.getCosmWasmClient()
const creationFee: Coin | null =
minterType === 'vending'
? whitelistDetails?.whitelistType === 'flex'
? vendingMinterFlexCreationFee
: collectionDetails?.updatable
? vendingMinterUpdatableCreationFee
: vendingMinterCreationFee
: collectionDetails?.updatable
? baseMinterUpdatableCreationFee
: baseMinterCreationFee
const creationFeeDenom = tokensList.find((token) => token.denom === creationFee?.denom)
await queryClient.getBalance(wallet.address || '', 'ustars').then(async (starsBalance) => {
await queryClient
.getBalance(wallet.address || '', creationFee?.denom as string)
.then((creationFeeDenomBalance) => {
if (minterType === 'vending' && whitelistDetails?.whitelistState === 'new') {
if (whitelistDetails.whitelistType !== 'merkletree' && whitelistDetails.memberLimit) {
const whitelistCreationFee = Math.ceil(Number(whitelistDetails.memberLimit) / 1000) * 100000000
if (creationFee?.denom === 'ustars') {
const amountNeeded = whitelistCreationFee + Number(creationFee.amount)
if (amountNeeded >= Number(starsBalance.amount))
throw new Error(
`Insufficient wallet balance to instantiate the required contracts. Needed amount: ${(
amountNeeded / 1000000
).toString()} STARS`,
)
} else {
if (whitelistCreationFee >= Number(starsBalance.amount))
throw new Error(
`Insufficient wallet balance to instantiate the whitelist. Needed amount: ${(
whitelistCreationFee / 1000000
).toString()} STARS`,
)
if (Number(creationFee?.amount) > Number(creationFeeDenomBalance.amount))
throw new Error(
`Insufficient wallet balance to instantiate the required contracts. Needed amount: ${(
Number(creationFee?.amount) / 1000000
).toString()} ${creationFeeDenom ? creationFeeDenom.displayName : creationFee?.denom}`,
)
}
} else if (whitelistDetails.whitelistType === 'merkletree') {
const merkleWhitelistCreationFee = 1000000000
if (creationFee?.denom === 'ustars') {
const amountNeeded = merkleWhitelistCreationFee + Number(creationFee.amount)
if (amountNeeded >= Number(starsBalance.amount))
throw new Error(
`Insufficient wallet balance to instantiate the required contracts. Needed amount: ${(
amountNeeded / 1000000
).toString()} STARS`,
)
} else {
if (merkleWhitelistCreationFee >= Number(starsBalance.amount))
throw new Error(
`Insufficient wallet balance to instantiate the whitelist. Needed amount: ${(
merkleWhitelistCreationFee / 1000000
).toString()} STARS`,
)
if (Number(creationFee?.amount) > Number(creationFeeDenomBalance.amount))
throw new Error(
`Insufficient wallet balance to instantiate the required contracts. Needed amount: ${(
Number(creationFee?.amount) / 1000000
).toString()} ${creationFeeDenom ? creationFeeDenom.displayName : creationFee?.denom}`,
)
}
}
} else if (Number(creationFee?.amount) > Number(creationFeeDenomBalance.amount))
throw new Error(
`Insufficient wallet balance to instantiate the required contracts. Needed amount: ${(
amountNeeded / 1000000
).toString()} STARS`,
Number(creationFee?.amount) / 1000000
).toString()} ${creationFeeDenom ? creationFeeDenom.displayName : creationFee?.denom}`,
)
} else if (whitelistDetails.whitelistType === 'merkletree') {
const amountNeeded =
1000000000 +
(collectionDetails?.updatable
? Number(vendingMinterUpdatableCreationFee)
: Number(vendingMinterCreationFee))
if (amountNeeded >= Number(balance.amount))
throw new Error(
`Insufficient wallet balance to instantiate the required contracts. Needed amount: ${(
amountNeeded / 1000000
).toString()} STARS`,
)
}
} else {
const amountNeeded =
minterType === 'vending'
? whitelistDetails?.whitelistState === 'existing' && whitelistDetails.whitelistType === 'flex'
? Number(vendingMinterFlexCreationFee)
: collectionDetails?.updatable
? Number(vendingMinterUpdatableCreationFee)
: Number(vendingMinterCreationFee)
: collectionDetails?.updatable
? Number(baseMinterUpdatableCreationFee)
: Number(baseMinterCreationFee)
if (amountNeeded >= Number(balance.amount))
throw new Error(
`Insufficient wallet balance to instantiate the required contracts. Needed amount: ${(
amountNeeded / 1000000
).toString()} STARS`,
)
}
})
})
}
@ -1934,7 +1958,7 @@ const CollectionCreationPage: NextPage = () => {
onChange={setOpenEditionMinterCreatorData}
onDetailsChange={setOpenEditionMinterDetails}
openEditionFactoryAddress={openEditionFactoryAddress}
openEditionMinterCreationFee={openEditionMinterCreationFee as string}
openEditionMinterCreationFee={openEditionMinterCreationFee}
/>
</Conditional>
<div className="mx-10">

View File

@ -60,6 +60,12 @@ const CollectionList: NextPage = () => {
if (minterConfig?.whitelist) collection.whitelist = minterConfig.whitelist
setMyStandardCollections((prevState) => [...prevState, collection])
} else if (contractType?.includes('open-edition')) {
const minterConfig = await (await wallet.getCosmWasmClient())
.queryContractSmart(collection.minter, { config: {} })
.catch(() => {
console.log('Unable to retrieve minter config')
})
if (minterConfig?.whitelist) collection.whitelist = minterConfig.whitelist
setMyOpenEditionCollections((prevState) => [...prevState, collection])
}
})
@ -429,6 +435,31 @@ const CollectionList: NextPage = () => {
</Tooltip>
</span>
</div>
<Conditional test={collection.whitelist}>
<div className="flex flex-row items-center space-x-3">
Whitelist:
<span className="ml-2">
<Tooltip
backgroundColor="bg-blue-500"
label="Click to copy the whitelist contract address"
>
<button
className="group flex space-x-2 font-mono text-base text-white/80 hover:underline"
onClick={() => void copy(collection.whitelist as string)}
type="button"
>
<span>
{truncateMiddle(
collection.whitelist ? (collection.whitelist as string) : '',
36,
)}
</span>
<FaCopy className="opacity-0 group-hover:opacity-100" />
</button>
</Tooltip>
</span>
</div>
</Conditional>
</td>
<th className="bg-black">
<div className="flex items-center space-x-8">
@ -445,6 +476,14 @@ const CollectionList: NextPage = () => {
>
<FaRocket />
</Anchor>
<Conditional test={collection.whitelist}>
<Anchor
className="text-xl text-white"
href={`/contracts/whitelist/execute/?contractAddress=${collection.whitelist}`}
>
<FaList />
</Anchor>
</Conditional>
</div>
</th>
</tr>

View File

@ -1,14 +1,28 @@
/* eslint-disable eslint-comments/disable-enable-pair */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import type { EncodeObject } from '@cosmjs/proto-signing'
import { GasPrice, SigningStargateClient } from '@cosmjs/stargate'
import clsx from 'clsx'
import { Alert } from 'components/Alert'
import { Button } from 'components/Button'
import { Conditional } from 'components/Conditional'
import { ContractPageHeader } from 'components/ContractPageHeader'
import { AddressList } from 'components/forms/AddressList'
import { useAddressListState } from 'components/forms/AddressList.hooks'
import { TextInput } from 'components/forms/FormInput'
import { useInputState } from 'components/forms/FormInput.hooks'
import { JsonPreview } from 'components/JsonPreview'
import { getConfig } from 'config'
import { MsgExec } from 'cosmjs-types/cosmos/authz/v1beta1/tx'
import { MsgStoreCode } from 'cosmjs-types/cosmwasm/wasm/v1/tx'
import { AccessConfig, AccessType } from 'cosmjs-types/cosmwasm/wasm/v1/types'
import type { NextPage } from 'next'
import { NextSeo } from 'next-seo'
import pako from 'pako'
import { useEffect, useRef, useState } from 'react'
import { toast } from 'react-hot-toast'
import { FaAsterisk } from 'react-icons/fa'
@ -23,9 +37,38 @@ const UploadContract: NextPage = () => {
const [transactionResult, setTransactionResult] = useState<any>()
const [wasmFile, setWasmFile] = useState<File | null>(null)
const [wasmByteArray, setWasmByteArray] = useState<Uint8Array | null>(null)
const [accessType, setAccessType] = useState<
'ACCESS_TYPE_UNSPECIFIED' | 'ACCESS_TYPE_EVERYBODY' | 'ACCESS_TYPE_ANY_OF_ADDRESSES' | 'ACCESS_TYPE_NOBODY'
>('ACCESS_TYPE_UNSPECIFIED')
const [accessConfig, setAccessConfig] = useState<AccessConfig | undefined>(undefined)
const [isAuthzUpload, setIsAuthzUpload] = useState(false)
const granterAddressState = useInputState({
id: 'address',
name: 'Granter Address',
title: 'Granter Address',
subtitle: 'The address that granted the authorization for contract upload',
defaultValue: '',
placeholder: 'stars1...',
})
const memoState = useInputState({
id: 'memo',
name: 'Memo',
title: 'Transaction Memo',
defaultValue: '',
placeholder: 'My contract',
})
const permittedAddressListState = useAddressListState()
const inputFile = useRef<HTMLInputElement>(null)
interface MsgExecAllowanceEncodeObject extends EncodeObject {
readonly typeUrl: '/cosmos.authz.v1beta1.MsgExec'
readonly value: Partial<MsgExec>
}
const onFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
if (!e.target.files) return
setWasmFile(e.target.files[0])
@ -51,20 +94,70 @@ const UploadContract: NextPage = () => {
try {
if (!wallet.isWalletConnected) return toast.error('Please connect your wallet.')
if (!wasmFile || !wasmByteArray) return toast.error('No file selected.')
if (accessType === 'ACCESS_TYPE_UNSPECIFIED')
return toast.error('Please select an instantiation permission type.', { style: { maxWidth: 'none' } })
setLoading(true)
const client = await wallet.getSigningCosmWasmClient()
const result = await client.upload(wallet.address as string, wasmByteArray, 'auto')
if (!isAuthzUpload) {
const result = await client.upload(
wallet.address as string,
wasmByteArray,
'auto',
memoState.value ?? undefined,
accessConfig,
)
setTransactionResult({
transactionHash: result.transactionHash,
codeId: result.codeId,
originalSize: result.originalSize,
compressedSize: result.compressedSize,
originalChecksum: result.checksum,
})
} else {
if (!granterAddressState.value) {
setLoading(false)
return toast.error('Please enter the authorization granter address.', { style: { maxWidth: 'none' } })
}
const compressed = pako.gzip(wasmByteArray, { level: 9 })
setTransactionResult({
transactionHash: result.transactionHash,
codeId: result.codeId,
originalSize: result.originalSize,
compressedSize: result.compressedSize,
originalChecksum: result.checksum,
})
const authzExecuteContractMsg: MsgExecAllowanceEncodeObject = {
typeUrl: '/cosmos.authz.v1beta1.MsgExec',
value: MsgExec.fromPartial({
grantee: wallet.address as string,
msgs: [
{
typeUrl: '/cosmwasm.wasm.v1.MsgStoreCode',
value: MsgStoreCode.encode({
sender: granterAddressState.value,
wasmByteCode: compressed,
instantiatePermission: accessConfig,
}).finish(),
},
],
}),
}
const offlineSigner = wallet.getOfflineSignerDirect()
const stargateClient = await SigningStargateClient.connectWithSigner(getConfig(NETWORK).rpcUrl, offlineSigner, {
gasPrice: GasPrice.fromString('0.025ustars'),
})
const result = await stargateClient.signAndBroadcast(
wallet.address || '',
[authzExecuteContractMsg],
'auto',
memoState.value ?? undefined,
)
setTransactionResult({
transactionHash: result.transactionHash,
codeId: result.events.filter((event) => event.type === 'store_code')[0].attributes[1].value,
originalChecksum: result.events.filter((event) => event.type === 'store_code')[0].attributes[0].value,
})
}
setLoading(false)
} catch (err: any) {
@ -73,55 +166,120 @@ const UploadContract: NextPage = () => {
}
}
useEffect(() => {
try {
if (accessType === 'ACCESS_TYPE_ANY_OF_ADDRESSES') {
setAccessConfig(
AccessConfig.fromPartial({
permission: AccessType.ACCESS_TYPE_ANY_OF_ADDRESSES,
addresses: permittedAddressListState.entries.map((entry) => entry[1].address).filter(Boolean),
}),
)
} else if (accessType === 'ACCESS_TYPE_NOBODY') {
setAccessConfig(AccessConfig.fromPartial({ permission: AccessType.ACCESS_TYPE_NOBODY }))
} else if (accessType === 'ACCESS_TYPE_EVERYBODY') {
setAccessConfig(AccessConfig.fromPartial({ permission: AccessType.ACCESS_TYPE_EVERYBODY }))
} else if (accessType === 'ACCESS_TYPE_UNSPECIFIED') {
setAccessConfig(undefined)
}
} catch (error: any) {
toast.error(error.message, { style: { maxWidth: 'none' } })
}
}, [accessType, permittedAddressListState.entries])
return (
<section className="py-6 px-12 space-y-4">
<Conditional test={NETWORK === 'testnet'}>
<NextSeo title="Upload Contract" />
<ContractPageHeader
description="Here you can upload a contract on Stargaze Testnet."
link=""
title="Upload Contract"
/>
<div className="inset-x-0 bottom-0 border-b-2 border-white/25" />
<NextSeo title="Upload Contract" />
<ContractPageHeader
description="Here you can upload a contract on Stargaze Testnet."
link=""
title="Upload Contract"
/>
<div className="inset-x-0 bottom-0 border-b-2 border-white/25" />
<Conditional test={Boolean(transactionResult)}>
<Alert type="info">
<b>Upload success!</b> Here is the transaction result containing the code ID, transaction hash and other
data.
</Alert>
<JsonPreview content={transactionResult} title="Transaction Result" />
<br />
</Conditional>
<div
className={clsx(
'flex relative justify-center items-center space-y-4 h-32',
'rounded border-2 border-white/20 border-dashed',
)}
<div className="flex flex-col w-1/2">
<span className="text-xl font-bold text-white">Authorization Type for Contract Instantiation</span>
<select
className="px-4 pt-2 pb-2 mt-2 w-1/2 placeholder:text-white/50 bg-white/10 rounded border-2 border-white/20 focus:ring focus:ring-plumbus-20"
onChange={(e) => setAccessType(e.target.value as any)}
value={accessType}
>
<option disabled value="ACCESS_TYPE_UNSPECIFIED">
Select Authorization Type
</option>
<option value="ACCESS_TYPE_EVERYBODY">Everybody</option>
<option value="ACCESS_TYPE_ANY_OF_ADDRESSES">Any of Addresses</option>
<option value="ACCESS_TYPE_NOBODY">Nobody</option>
</select>
</div>
<div className="my-2 w-1/2">
<TextInput {...memoState} />
</div>
<div className="flex flex-row justify-start">
<h1 className="mt-2 font-bold text-md">Authz Upload?</h1>
<label className="justify-start ml-6 cursor-pointer label">
<input
accept=".wasm"
className={clsx(
'file:py-2 file:px-4 file:mr-4 file:bg-plumbus-light file:rounded file:border-0 cursor-pointer',
'before:absolute before:inset-0 before:hover:bg-white/5 before:transition',
)}
onChange={onFileChange}
ref={inputFile}
type="file"
checked={isAuthzUpload}
className={`${isAuthzUpload ? `bg-stargaze` : `bg-gray-600`} checkbox`}
onClick={() => {
setIsAuthzUpload(!isAuthzUpload)
}}
type="checkbox"
/>
</label>
</div>
<Conditional test={isAuthzUpload}>
<div className="my-2 w-3/4">
<TextInput {...granterAddressState} />
</div>
</Conditional>
<Conditional test={accessType === 'ACCESS_TYPE_ANY_OF_ADDRESSES'}>
<div className="my-2 w-3/4">
<AddressList
entries={permittedAddressListState.entries}
onAdd={permittedAddressListState.add}
onChange={permittedAddressListState.update}
onRemove={permittedAddressListState.remove}
subtitle="The list of addresses permitted to instantiate the contract"
title="Permitted Addresses"
/>
</div>
</Conditional>
<div className="flex justify-end pb-6">
<Button isDisabled={!wasmFile} isLoading={loading} isWide leftIcon={<FaAsterisk />} onClick={upload}>
Upload Contract
</Button>
</div>
</Conditional>
<Conditional test={NETWORK === 'mainnet'}>
<NextSeo title="Upload Contract" />
<ContractPageHeader description="" link="" title="Upload Contract" />
<Alert type="info">Permissionless upload of contracts is only supported for testnet currently.</Alert>
<Conditional test={Boolean(transactionResult)}>
<Alert type="info">
<b>Upload success!</b> Here is the transaction result containing the code ID, transaction hash and other data.
</Alert>
<JsonPreview content={transactionResult} title="Transaction Result" />
<br />
</Conditional>
<div
className={clsx(
'flex relative justify-center items-center space-y-4 h-32',
'rounded border-2 border-white/20 border-dashed',
)}
>
<input
accept=".wasm"
className={clsx(
'file:py-2 file:px-4 file:mr-4 file:bg-plumbus-light file:rounded file:border-0 cursor-pointer',
'before:absolute before:inset-0 before:hover:bg-white/5 before:transition',
)}
onChange={onFileChange}
ref={inputFile}
type="file"
/>
</div>
<div className="flex justify-end pb-6">
<Button isDisabled={!wasmFile} isLoading={loading} isWide leftIcon={<FaAsterisk />} onClick={upload}>
Upload Contract
</Button>
</div>
</section>
)
}

69
scripts/publish-app-record.sh Executable file
View File

@ -0,0 +1,69 @@
#!/bin/bash
set -e
RECORD_FILE=tmp.rf.$$
CONFIG_FILE=`mktemp`
CERC_APP_TYPE=${CERC_APP_TYPE:-"webapp"}
CERC_REPO_REF=${CERC_REPO_REF:-${GITHUB_SHA:-`git log -1 --format="%H"`}}
CERC_IS_LATEST_RELEASE=${CERC_IS_LATEST_RELEASE:-"true"}
rcd_name=$(jq -r '.name' package.json | sed 's/null//')
rcd_desc=$(jq -r '.description' package.json | sed 's/null//')
rcd_repository=$(jq -r '.repository' package.json | sed 's/null//')
rcd_homepage=$(jq -r '.homepage' package.json | sed 's/null//')
rcd_license=$(jq -r '.license' package.json | sed 's/null//')
rcd_author=$(jq -r '.author' package.json | sed 's/null//')
rcd_app_version=$(jq -r '.version' package.json | sed 's/null//')
cat <<EOF > "$CONFIG_FILE"
services:
cns:
restEndpoint: '${CERC_REGISTRY_REST_ENDPOINT:-http://23.111.69.218:1317}'
gqlEndpoint: '${CERC_REGISTRY_GQL_ENDPOINT:-https://lx-daemon.audubon.app/api}'
chainId: ${CERC_REGISTRY_CHAIN_ID:-laconic_9000-1}
gas: 9550000
fees: 500000aphoton
EOF
next_ver=$(laconic -c $CONFIG_FILE cns record list --type ApplicationRecord --all --name "$rcd_name" 2>/dev/null | jq -r -s ".[] | sort_by(.createTime) | reverse | [ .[] | select(.bondId == \"$CERC_REGISTRY_BOND_ID\") ] | .[0].attributes.version" | awk -F. -v OFS=. '{$NF += 1 ; print}')
if [ -z "$next_ver" ] || [ "1" == "$next_ver" ]; then
next_ver=0.0.1
fi
cat <<EOF | sed '/.*: ""$/d' > "$RECORD_FILE"
record:
type: ApplicationRecord
version: ${next_ver}
name: "$rcd_name"
description: "$rcd_desc"
homepage: "$rcd_homepage"
license: "$rcd_license"
author: "$rcd_author"
repository:
- "$rcd_repository"
repository_ref: "$CERC_REPO_REF"
app_version: "$rcd_app_version"
app_type: "$CERC_APP_TYPE"
EOF
cat $RECORD_FILE
RECORD_ID=$(laconic -c $CONFIG_FILE cns record publish --filename $RECORD_FILE --user-key "${CERC_REGISTRY_USER_KEY}" --bond-id ${CERC_REGISTRY_BOND_ID} | jq -r '.id')
echo $RECORD_ID
if [ -z "$CERC_REGISTRY_APP_CRN" ]; then
authority=$(echo "$rcd_name" | cut -d'/' -f1 | sed 's/@//')
app=$(echo "$rcd_name" | cut -d'/' -f2-)
CERC_REGISTRY_APP_CRN="crn://$authority/applications/$app"
fi
laconic -c $CONFIG_FILE cns name set --user-key "${CERC_REGISTRY_USER_KEY}" --bond-id ${CERC_REGISTRY_BOND_ID} "$CERC_REGISTRY_APP_CRN@${rcd_app_version}" "$RECORD_ID"
laconic -c $CONFIG_FILE cns name set --user-key "${CERC_REGISTRY_USER_KEY}" --bond-id ${CERC_REGISTRY_BOND_ID} "$CERC_REGISTRY_APP_CRN@${CERC_REPO_REF}" "$RECORD_ID"
if [ "true" == "$CERC_IS_LATEST_RELEASE" ]; then
laconic -c $CONFIG_FILE cns name set --user-key "${CERC_REGISTRY_USER_KEY}" --bond-id ${CERC_REGISTRY_BOND_ID} "$CERC_REGISTRY_APP_CRN" "$RECORD_ID"
fi
rm -f $RECORD_FILE $CONFIG_FILE

View File

@ -0,0 +1,56 @@
#!/bin/bash
set -e
RECORD_FILE=tmp.rf.$$
CONFIG_FILE=`mktemp`
rcd_name=$(jq -r '.name' package.json | sed 's/null//' | sed 's/^@//')
rcd_app_version=$(jq -r '.version' package.json | sed 's/null//')
cat <<EOF > "$CONFIG_FILE"
services:
cns:
restEndpoint: '${CERC_REGISTRY_REST_ENDPOINT:-http://23.111.69.218:1317}'
gqlEndpoint: '${CERC_REGISTRY_GQL_ENDPOINT:-https://lx-daemon.audubon.app/api}'
chainId: ${CERC_REGISTRY_CHAIN_ID:-laconic_9000-1}
gas: 550000
fees: 200000aphoton
EOF
if [ -z "$CERC_REGISTRY_APP_CRN" ]; then
authority=$(echo "$rcd_name" | cut -d'/' -f1 | sed 's/@//')
app=$(echo "$rcd_name" | cut -d'/' -f2-)
CERC_REGISTRY_APP_CRN="crn://$authority/applications/$app"
fi
APP_RECORD=$(laconic -c $CONFIG_FILE cns name resolve "$CERC_REGISTRY_APP_CRN" | jq '.[0]')
if [ -z "$APP_RECORD" ] || [ "null" == "$APP_RECORD" ]; then
echo "No record found for $CERC_REGISTRY_APP_CRN."
exit 1
fi
cat <<EOF | sed '/.*: ""$/d' > "$RECORD_FILE"
record:
type: ApplicationDeploymentRequest
version: 1.0.0
name: "$rcd_name@$rcd_app_version"
application: "$CERC_REGISTRY_APP_CRN@$rcd_app_version"
dns: "$CERC_REGISTRY_DEPLOYMENT_SHORT_HOSTNAME"
deployment: "$CERC_REGISTRY_DEPLOYMENT_CRN"
config:
env:
# this overrides the setting in `.env`
CERC_WEBAPP_DEBUG: "$rcd_app_version"
CERC_MAX_GENERATE_TIME: "600"
meta:
note: "Added by CI @ `date`"
repository: "`git remote get-url origin`"
repository_ref: "${GITHUB_SHA:-`git log -1 --format="%H"`}"
EOF
cat $RECORD_FILE
RECORD_ID=$(laconic -c $CONFIG_FILE cns record publish --filename $RECORD_FILE --user-key "${CERC_REGISTRY_USER_KEY}" --bond-id ${CERC_REGISTRY_BOND_ID} | jq -r '.id')
echo $RECORD_ID
rm -f $RECORD_FILE $CONFIG_FILE

3489
yarn.lock

File diff suppressed because it is too large Load Diff