diff --git a/packages/demo/components/pages/apis/transaction/builder/delegateStakeCertificate.tsx b/packages/demo/components/pages/apis/transaction/builder/delegateStakeCertificate.tsx new file mode 100644 index 000000000..a56e92b0d --- /dev/null +++ b/packages/demo/components/pages/apis/transaction/builder/delegateStakeCertificate.tsx @@ -0,0 +1,28 @@ +import Section from '../../../../common/section'; +import Codeblock from '../../../../ui/codeblock'; + +export default function DeregisterCertificate() { + return ( +
+ ); +} + +function Content() { + let code = `mesh + .delegateStakeCertificate(stakeKeyHash: string, poolId: string)`; + + return ( + <> +

+ Use .delegateStakeCertificate() to delegate a stake to a + pool: +

+ + + + ); +} diff --git a/packages/demo/components/pages/apis/transaction/builder/deregisterCertificate.tsx b/packages/demo/components/pages/apis/transaction/builder/deregisterCertificate.tsx new file mode 100644 index 000000000..070781248 --- /dev/null +++ b/packages/demo/components/pages/apis/transaction/builder/deregisterCertificate.tsx @@ -0,0 +1,28 @@ +import Section from '../../../../common/section'; +import Codeblock from '../../../../ui/codeblock'; + +export default function DeregisterCertificate() { + return ( +
+ ); +} + +function Content() { + let code = `mesh + .deregisterStakeCertificate(stakeKeyHash: string)`; + + return ( + <> +

+ Use .deregisterStakeCertificate() to deregister a stake + certificate: +

+ + + + ); +} diff --git a/packages/demo/components/pages/apis/transaction/builder/mintNative.tsx b/packages/demo/components/pages/apis/transaction/builder/mintNative.tsx index 5aeb2e521..7abee46eb 100644 --- a/packages/demo/components/pages/apis/transaction/builder/mintNative.tsx +++ b/packages/demo/components/pages/apis/transaction/builder/mintNative.tsx @@ -13,15 +13,18 @@ export default function Mint() { function Content() { let code = `mesh - .mint(quantity: number, policy: string, name: string) + .mint(quantity: string, policy: string, name: string) .mintingScript(scriptCbor: string) `; return ( <> -

When minting tokens using a 'native script' as input, there are 2 steps:

+

+ When minting tokens using a 'native script' as input, there are 2 steps: +

- 1. Providing the minting value (quantity, policy and name) using .mint() + 1. Providing the minting value (quantity, policy and name) using{' '} + .mint()

2. Providing the script source using diff --git a/packages/demo/components/pages/apis/transaction/builder/mintPlutus.tsx b/packages/demo/components/pages/apis/transaction/builder/mintPlutus.tsx index 0b475d51d..2c52d180d 100644 --- a/packages/demo/components/pages/apis/transaction/builder/mintPlutus.tsx +++ b/packages/demo/components/pages/apis/transaction/builder/mintPlutus.tsx @@ -14,7 +14,7 @@ export default function Mint() { function Content() { let code = `mesh .mintPlutusScriptV2() - .mint(quantity: number, policy: string, name: string) + .mint(quantity: string, policy: string, name: string) .mintTxInReference(txHash: string, txIndex: number) // or .mintingScript(scriptCbor: string) .mintRedeemerValue(redeemer: Data | object | string, exUnits?: Budget, type?: "Mesh" | "CBOR" | "JSON") `; diff --git a/packages/demo/components/pages/apis/transaction/builder/registerCertificate.tsx b/packages/demo/components/pages/apis/transaction/builder/registerCertificate.tsx new file mode 100644 index 000000000..a94b155b7 --- /dev/null +++ b/packages/demo/components/pages/apis/transaction/builder/registerCertificate.tsx @@ -0,0 +1,28 @@ +import Section from '../../../../common/section'; +import Codeblock from '../../../../ui/codeblock'; + +export default function RegisterCertificate() { + return ( +
+ ); +} + +function Content() { + let code = `mesh + .registerStakeCertificate(stakeKeyHash: string)`; + + return ( + <> +

+ Use .registerStakeCertificate() to register a stake + certificate: +

+ + + + ); +} diff --git a/packages/demo/components/pages/apis/transaction/builder/registerPoolCertificate.tsx b/packages/demo/components/pages/apis/transaction/builder/registerPoolCertificate.tsx new file mode 100644 index 000000000..460b3bcf9 --- /dev/null +++ b/packages/demo/components/pages/apis/transaction/builder/registerPoolCertificate.tsx @@ -0,0 +1,28 @@ +import Section from '../../../../common/section'; +import Codeblock from '../../../../ui/codeblock'; + +export default function RegisterPoolCertificate() { + return ( +
+ ); +} + +function Content() { + let code = `mesh + .registerPoolCertificate(poolParams: PoolParams)`; + + return ( + <> +

+ Use .registerPoolCertificate() to register a pool + certificate: +

+ + + + ); +} diff --git a/packages/demo/components/pages/apis/transaction/builder/retirePoolCertificate.tsx b/packages/demo/components/pages/apis/transaction/builder/retirePoolCertificate.tsx new file mode 100644 index 000000000..c52ba4919 --- /dev/null +++ b/packages/demo/components/pages/apis/transaction/builder/retirePoolCertificate.tsx @@ -0,0 +1,27 @@ +import Section from '../../../../common/section'; +import Codeblock from '../../../../ui/codeblock'; + +export default function RetirePoolCertificate() { + return ( +
+ ); +} + +function Content() { + let code = `mesh + .retirePoolCertificate(poolId: string, epoch: number)`; + + return ( + <> +

+ Use .retirePoolCertificate() to retire a pool certificate: +

+ + + + ); +} diff --git a/packages/demo/components/pages/apis/transaction/builder/schemas.tsx b/packages/demo/components/pages/apis/transaction/builder/schemas.tsx index 2d56abc9f..7486ddcaa 100644 --- a/packages/demo/components/pages/apis/transaction/builder/schemas.tsx +++ b/packages/demo/components/pages/apis/transaction/builder/schemas.tsx @@ -6,22 +6,23 @@ export default function Schemas() { } function Content() { - let codeMeshTxBuilderBody = ``; - codeMeshTxBuilderBody += `MeshTxBuilderBody = {\n`; - codeMeshTxBuilderBody += ` inputs: TxIn[]\n`; - codeMeshTxBuilderBody += ` outputs: Output[];\n`; - codeMeshTxBuilderBody += ` collaterals: PubKeyTxIn[];\n`; - codeMeshTxBuilderBody += ` requiredSignatures: string[];\n`; - codeMeshTxBuilderBody += ` referenceInputs: RefTxIn[];\n`; - codeMeshTxBuilderBody += ` mints: MintItem[];\n`; - codeMeshTxBuilderBody += ` changeAddress: string;\n`; - codeMeshTxBuilderBody += ` metadata: Metadata[];\n`; - codeMeshTxBuilderBody += ` validityRange: ValidityRange;\n`; - codeMeshTxBuilderBody += ` signingKey: string[];\n`; - codeMeshTxBuilderBody += `}\n`; - - let codeInput = ``; - codeInput += `TxIn = PubKeyTxIn | ScriptTxIn;\n`; + let codeMeshTxBuilderBody = `MeshTxBuilderBody = { + inputs: TxIn[]; + outputs: Output[]; + extraInputs: UTxO[]; + selectionThreshold: number; + collaterals: PubKeyTxIn[]; + requiredSignatures: string[]; + referenceInputs: RefTxIn[]; + mints: MintItem[]; + changeAddress: string; + metadata: Metadata[]; + validityRange: ValidityRange; + certificates: Certificate[]; + signingKey: string[]; +}`; + + let codeInput = `TxIn = PubKeyTxIn | ScriptTxIn;`; let codePubKeyTxIn = `PubKeyTxIn = { type: 'PubKey'; @@ -97,7 +98,7 @@ function Content() { type: 'Plutus' | 'Native'; policyId: string; assetName: string; - amount: number; + amount: string; redeemer?: Redeemer; scriptSource?: | { diff --git a/packages/demo/components/pages/apis/transaction/builderExample/complexTransaction.tsx b/packages/demo/components/pages/apis/transaction/builderExample/complexTransaction.tsx index 619e30086..0bbb92d8a 100644 --- a/packages/demo/components/pages/apis/transaction/builderExample/complexTransaction.tsx +++ b/packages/demo/components/pages/apis/transaction/builderExample/complexTransaction.tsx @@ -20,7 +20,7 @@ function Content() { .txInRedeemerValue(mConStr0([])) .txInScript(getScriptCbor("Spending")) .mintPlutusScriptV2() - .mint(1, policyId, tokenName) + .mint("1", policyId, tokenName) .mintingScript(mintingScript) .mintRedeemerValue(mConStr0([])) .txOut(this.constants.walletAddress, [{ unit: policyId + tokenName, quantity: "1" }]) diff --git a/packages/demo/components/pages/apis/transaction/builderExample/mintToken.tsx b/packages/demo/components/pages/apis/transaction/builderExample/mintToken.tsx index 7f2001316..c11179317 100644 --- a/packages/demo/components/pages/apis/transaction/builderExample/mintToken.tsx +++ b/packages/demo/components/pages/apis/transaction/builderExample/mintToken.tsx @@ -15,7 +15,7 @@ function Content() { const codeSnippet = `await mesh .txIn(txInHash, txInId) .mintPlutusScriptV2() - .mint(1, policyId, tokenName) + .mint("1", policyId, tokenName) .mintingScript(mintingScript) .mintRedeemerValue(mConStr0([])) .txOut(this.constants.walletAddress, [{ unit: policyId + tokenName, quantity: "1" }]) diff --git a/packages/demo/components/pages/apis/transaction/builderExample/staking.tsx b/packages/demo/components/pages/apis/transaction/builderExample/staking.tsx new file mode 100644 index 000000000..b604068f7 --- /dev/null +++ b/packages/demo/components/pages/apis/transaction/builderExample/staking.tsx @@ -0,0 +1,39 @@ +import Section from '../../../../common/section'; +import Codeblock from '../../../../ui/codeblock'; + +export default function Staking() { + return ( +
+ ); +} + +function Content() { + const codeSnippet = `const usedAddress = await wallet.getUnusedAddresses(); +const { stakeCredential } = serializeBech32Address(usedAddress[0]); +await mesh + .txIn(txInHash, txInId) + .registerStakeCertificate(stakeCredential) // Skip this line if you are not staking for the first time + .delegateStakeCertificate( + stakeCredential, + 'poolxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' + ) + .changeAddress(changeAddress) + .complete(); + +const signedTx = mesh.completeSigning()`; + + return ( + <> +

+ The following shows a simple example of building a transaction to + (register stake certificate and) delegate stake to a pool for the first + time. +

+ + + ); +} diff --git a/packages/demo/pages/apis/transaction/builder.tsx b/packages/demo/pages/apis/transaction/builder.tsx index 7ec1b9b49..0ed81d281 100644 --- a/packages/demo/pages/apis/transaction/builder.tsx +++ b/packages/demo/pages/apis/transaction/builder.tsx @@ -5,7 +5,6 @@ import CommonLayout from '../../../components/common/layout'; import InvalidInterval from '../../../components/pages/apis/transaction/builder/InvalidInterval'; import ChangeAddress from '../../../components/pages/apis/transaction/builder/changeAddress'; import Complete from '../../../components/pages/apis/transaction/builder/complete'; -import Schemas from '../../../components/pages/apis/transaction/builder/schemas'; import MetadataValue from '../../../components/pages/apis/transaction/builder/metadataValue'; import MintPlutus from '../../../components/pages/apis/transaction/builder/mintPlutus'; import MintNative from '../../../components/pages/apis/transaction/builder/mintNative'; @@ -18,6 +17,11 @@ import TxInCollateral from '../../../components/pages/apis/transaction/builder/t import TxOut from '../../../components/pages/apis/transaction/builder/txOut'; import CommonHero from '../../../components/pages/apis/transaction/commonHero'; import Metatags from '../../../components/site/metatags'; +import RegisterCertificate from '../../../components/pages/apis/transaction/builder/registerCertificate'; +import DeregisterCertificate from '../../../components/pages/apis/transaction/builder/deregisterCertificate'; +import DelegateStakeCertificate from '../../../components/pages/apis/transaction/builder/delegateStakeCertificate'; +import RegisterPoolCertificate from '../../../components/pages/apis/transaction/builder/registerPoolCertificate'; +import RetirePoolCertificate from '../../../components/pages/apis/transaction/builder/retirePoolCertificate'; const TransactionBuilderPage: NextPage = () => { const sidebarItems = [ @@ -56,6 +60,26 @@ const TransactionBuilderPage: NextPage = () => { label: 'Add metadata', to: 'metadataValue', }, + { + label: 'Register Stake Certificate', + to: 'registerCertificate', + }, + { + label: 'Deregister Stake Certificate', + to: 'deregisterCertificate', + }, + { + label: 'Delegate Stake', + to: 'delegateStakeCertificate', + }, + { + label: 'Register Pool Certificate', + to: 'registerPoolCertificate', + }, + { + label: 'Retire Pool Certificate', + to: 'retirePoolCertificate', + }, { label: 'Sign with signing key', to: 'signingKey', @@ -64,10 +88,6 @@ const TransactionBuilderPage: NextPage = () => { label: 'Complete transaction building', to: 'complete', }, - { - label: 'Schemas', - to: 'schemas', - }, ]; return ( @@ -101,9 +121,13 @@ const TransactionBuilderPage: NextPage = () => { + + + + + - ); diff --git a/packages/demo/pages/apis/transaction/builderExample.tsx b/packages/demo/pages/apis/transaction/builderExample.tsx index b5b3bac09..6207615f9 100644 --- a/packages/demo/pages/apis/transaction/builderExample.tsx +++ b/packages/demo/pages/apis/transaction/builderExample.tsx @@ -12,6 +12,7 @@ import Metatags from '../../../components/site/metatags'; import LockFund from '../../../components/pages/apis/transaction/builderExample/lockFund'; import UnlockFund from '../../../components/pages/apis/transaction/builderExample/unlockFund'; import MintToken from '../../../components/pages/apis/transaction/builderExample/mintToken'; +import Staking from '../../../components/pages/apis/transaction/builderExample/staking'; const TransactionBuilderExamplePage: NextPage = () => { const sidebarItems = [ @@ -20,6 +21,7 @@ const TransactionBuilderExamplePage: NextPage = () => { { label: 'Lock Fund', to: 'lockFund' }, { label: 'Unlock Fund', to: 'unlockFund' }, { label: 'Mint Tokens', to: 'mintToken' }, + { label: 'Delegate Stake', to: 'staking' }, { label: 'Complex Transaction', to: 'complexTransaction' }, { label: 'Build without dependency', to: 'withoutDependency' }, { label: 'Build with object', to: 'withObject' }, @@ -50,6 +52,7 @@ const TransactionBuilderExamplePage: NextPage = () => { + diff --git a/packages/module/src/transaction/meshTxBuilder/meshTxBuilderCore.ts b/packages/module/src/transaction/meshTxBuilder/meshTxBuilderCore.ts index 160e4a3a3..1a3b8251a 100644 --- a/packages/module/src/transaction/meshTxBuilder/meshTxBuilderCore.ts +++ b/packages/module/src/transaction/meshTxBuilder/meshTxBuilderCore.ts @@ -12,6 +12,7 @@ import { Quantity, UTxO, Unit, + PoolParams, } from '@mesh/common/types'; import { buildTxBuilder, @@ -19,6 +20,7 @@ import { toPlutusData, toAddress, buildDataCost, + toRelay, } from '@mesh/common/utils'; import { csl } from '@mesh/core'; import { @@ -34,6 +36,8 @@ import { ValidityRange, Metadata, BuilderData, + Certificate, + TxInParameter, } from './type'; import { selectUtxos } from '@mesh/core/CPS-009'; @@ -93,6 +97,7 @@ export class MeshTxBuilderCore { changeAddress: '', metadata: [], validityRange: {}, + certificates: [], signingKey: [], }); @@ -140,6 +145,7 @@ export class MeshTxBuilderCore { referenceInputs, mints, changeAddress, + certificates, validityRange, requiredSignatures, metadata, @@ -161,6 +167,8 @@ export class MeshTxBuilderCore { this.addUtxosFrom(extraInputs, String(selectionThreshold)); } + this.removeDuplicateInputs(); + this.meshTxBuilderBody.mints.sort((a, b) => a.policyId.localeCompare(b.policyId) ); @@ -177,6 +185,7 @@ export class MeshTxBuilderCore { this.addAllCollaterals(collaterals); this.addAllReferenceInputs(referenceInputs); this.addAllMints(mints); + this.addAllCertificates(certificates); this.addValidityRange(validityRange); this.addAllRequiredSignatures(requiredSignatures); this.addAllMetadata(metadata); @@ -192,7 +201,7 @@ export class MeshTxBuilderCore { ) .reduce((acc, curr) => acc + parseInt(curr), 0); - const collateralEsimate = Math.ceil( + const collateralEstimate = Math.ceil( (this._protocolParams.collateralPercent * Number( Number( @@ -207,14 +216,14 @@ export class MeshTxBuilderCore { let collateralReturnNeeded = false; - if (totalCollateral - collateralEsimate > 0) { + if (totalCollateral - collateralEstimate > 0) { const collateralEstimateOutput = csl.TransactionOutput.new( csl.Address.from_bech32(changeAddress), - csl.Value.new(csl.BigNum.from_str(String(collateralEsimate))) + csl.Value.new(csl.BigNum.from_str(String(collateralEstimate))) ); if ( - totalCollateral - collateralEsimate > + totalCollateral - collateralEstimate > Number( csl .min_ada_for_output( @@ -639,7 +648,7 @@ export class MeshTxBuilderCore { * @param name The hex of token name of the asset to be minted * @returns The MeshTxBuilder instance */ - mint = (quantity: number, policy: string, name: string) => { + mint = (quantity: string, policy: string, name: string) => { if (this.mintItem) { this.queueMint(); } @@ -798,6 +807,76 @@ export class MeshTxBuilderCore { return this; }; + /** + * Creates a pool registration certificate, and adds it to the transaction + * @param poolParams Parameters for pool registration + * @returns The MeshTxBuilder instance + */ + registerPoolCertificate = (poolParams: PoolParams) => { + this.meshTxBuilderBody.certificates.push({ + type: 'RegisterPool', + poolParams, + }); + return this; + }; + + /** + * Creates a stake registration certificate, and adds it to the transaction + * @param stakeKeyHash The keyHash of the stake key + * @returns The MeshTxBuilder instance + */ + registerStakeCertificate = (stakeKeyHash: string) => { + this.meshTxBuilderBody.certificates.push({ + type: 'RegisterStake', + stakeKeyHash, + }); + return this; + }; + + /** + * Creates a stake delegation certificate, and adds it to the transaction + * This will delegate stake from the corresponding stake address to the pool + * @param stakeKeyHash The keyHash of the stake key + * @param poolId poolId can be in either bech32 or hex form + * @returns The MeshTxBuilder instance + */ + delegateStakeCertificate = (stakeKeyHash: string, poolId: string) => { + this.meshTxBuilderBody.certificates.push({ + type: 'DelegateStake', + stakeKeyHash, + poolId, + }); + return this; + }; + + /** + * Creates a stake deregister certificate, and adds it to the transaction + * @param stakeKeyHash The keyHash of the stake key + * @returns The MeshTxBuilder instance + */ + deregisterStakeCertificate = (stakeKeyHash: string) => { + this.meshTxBuilderBody.certificates.push({ + type: 'DeregisterStake', + stakeKeyHash, + }); + return this; + }; + + /** + * Creates a pool retire certificate, and adds it to the transaction + * @param poolId poolId can be in either bech32 or hex form + * @param epoch The intended epoch to retire the pool + * @returns The MeshTxBuilder instance + */ + retirePoolCertificate = (poolId: string, epoch: number) => { + this.meshTxBuilderBody.certificates.push({ + type: 'RetirePool', + poolId, + epoch, + }); + return this; + }; + /** * Configure the address to accept change UTxO * @param addr The address to accept change UTxO @@ -1000,6 +1079,23 @@ export class MeshTxBuilderCore { // Below protected functions for completing tx building + protected removeDuplicateInputs = () => { + const inputs = this.meshTxBuilderBody.inputs; + const getTxInId = (txIn: TxInParameter): string => { + return `${txIn.txHash}#${txIn.txIndex}`; + }; + const addedInputs: string[] = []; + for (let i = 0; i < inputs.length; i++) { + const currentTxInId = getTxInId(inputs[i].txIn); + if (addedInputs.includes(currentTxInId)) { + inputs.splice(i, 1); + i--; + } else { + addedInputs.push(currentTxInId); + } + } + }; + private addAllInputs = (inputs: TxIn[]) => { for (let i = 0; i < inputs.length; i++) { const currentTxIn = inputs[i]; //TODO: add type @@ -1236,7 +1332,7 @@ export class MeshTxBuilderCore { mintBuilder.add_asset( csl.MintWitness.new_plutus_script(script, newRedeemer), csl.AssetName.new(Buffer.from(assetName, 'hex')), - csl.Int.new_i32(amount) + csl.Int.new(csl.BigNum.from_str(amount)) ); }; @@ -1251,10 +1347,116 @@ export class MeshTxBuilderCore { csl.NativeScript.from_hex(scriptSource.script.code) ), csl.AssetName.new(Buffer.from(assetName, 'hex')), - csl.Int.new_i32(amount) + csl.Int.new(csl.BigNum.from_str(amount)) ); }; + private decimalToFraction( + decimal: number + ): [numerator: number, denominator: number] { + const powerOf10 = 10 ** decimal.toString().split('.')[1].length; + const numerator = decimal * powerOf10; + const denominator = powerOf10; + + return [numerator, denominator]; + } + + private toPoolParams = (poolParams: PoolParams): csl.PoolParams => { + const marginFraction = this.decimalToFraction(poolParams.margin); + const relays = csl.Relays.new(); + poolParams.relays.forEach((relay) => { + relays.add(toRelay(relay)); + }); + const rewardAddress = csl.RewardAddress.from_address( + csl.Address.from_bech32(poolParams.rewardAddress) + ); + if (rewardAddress === undefined) { + throw new Error('Reward address is invalid'); + } + const poolOwners = csl.Ed25519KeyHashes.new(); + poolParams.owners.forEach((owner) => { + poolOwners.add(csl.Ed25519KeyHash.from_hex(owner)); + }); + return csl.PoolParams.new( + csl.Ed25519KeyHash.from_hex(poolParams.operator), + csl.VRFKeyHash.from_hex(poolParams.VRFKeyHash), + csl.BigNum.from_str(poolParams.pledge), + csl.BigNum.from_str(poolParams.cost), + csl.UnitInterval.new( + csl.BigNum.from_str(marginFraction[0].toString()), + csl.BigNum.from_str(marginFraction[1].toString()) + ), + rewardAddress, + poolOwners, + relays, + poolParams.metadata + ? csl.PoolMetadata.from_json(JSON.stringify(poolParams.metadata)) + : undefined + ); + }; + + private addCertificate = ( + certificates: csl.Certificates, + cert: Certificate + ) => { + switch (cert.type) { + case 'RegisterPool': + certificates.add( + csl.Certificate.new_pool_registration( + csl.PoolRegistration.new(this.toPoolParams(cert.poolParams)) + ) + ); + break; + case 'RegisterStake': + certificates.add( + csl.Certificate.new_stake_registration( + csl.StakeRegistration.new( + csl.StakeCredential.from_keyhash( + csl.Ed25519KeyHash.from_hex(cert.stakeKeyHash) + ) + ) + ) + ); + break; + case 'DelegateStake': + certificates.add( + csl.Certificate.new_stake_delegation( + csl.StakeDelegation.new( + csl.StakeCredential.from_keyhash( + csl.Ed25519KeyHash.from_hex(cert.stakeKeyHash) + ), + cert.poolId.startsWith('pool') + ? csl.Ed25519KeyHash.from_bech32(cert.poolId) + : csl.Ed25519KeyHash.from_hex(cert.poolId) + ) + ) + ); + break; + case 'DeregisterStake': + certificates.add( + csl.Certificate.new_stake_deregistration( + csl.StakeDeregistration.new( + csl.StakeCredential.from_keyhash( + csl.Ed25519KeyHash.from_hex(cert.stakeKeyHash) + ) + ) + ) + ); + break; + case 'RetirePool': + certificates.add( + csl.Certificate.new_pool_retirement( + csl.PoolRetirement.new( + cert.poolId.startsWith('pool') + ? csl.Ed25519KeyHash.from_bech32(cert.poolId) + : csl.Ed25519KeyHash.from_hex(cert.poolId), + cert.epoch + ) + ) + ); + } + }; + protected queueAllLastItem = () => { if (this.txOutput) { this.meshTxBuilderBody.outputs.push(this.txOutput); @@ -1272,6 +1474,14 @@ export class MeshTxBuilderCore { } }; + protected addAllCertificates = (allCertificates: Certificate[]) => { + const certificates = csl.Certificates.new(); + allCertificates.forEach((cert) => { + this.addCertificate(certificates, cert); + }); + this.txBuilder.set_certs(certificates); + }; + protected addCostModels = () => { this.txBuilder.calc_script_data_hash( csl.TxBuilderConstants.plutus_vasil_cost_models() diff --git a/packages/module/src/transaction/meshTxBuilder/progress.md b/packages/module/src/transaction/meshTxBuilder/progress.md deleted file mode 100644 index 3a87ce424..000000000 --- a/packages/module/src/transaction/meshTxBuilder/progress.md +++ /dev/null @@ -1,46 +0,0 @@ -# Progress of Lower Level API - MeshTxBuilder - -## Core Apis - -| Method Name | Sync | cli | Tested | Remarks | -| --------------------------------------- | ---- | --- | ------ | ------------------------------------- | -| txIn | X | X | X | | -| txInDatumValue | | | | | -| txInInlineDatumPresent | X | X | X | | -| txOut | X | X | X | automate minUTxO not tested | -| txOutDatumHashValue | | | | | -| txOutInlineDatumValue | X | X | X | | -| txOutReferenceScript | X | X | | | -| spendingPlutusScriptV2 | X | X | X | | -| spendingTxInReference | X | X | X | | -| spendingReferenceTxInInlineDatumPresent | X | X | X | Identical with txInInlineDatumPresent | -| spendingReferenceTxInRedeemerValue | X | X | X | | -| readOnlyTxInReference | X | X | X | | -| mintPlutusScriptV2 | X | X | X | | -| mint | X | X | X | | -| mintTxInReference | X | X | X | | -| mintRedeemerValue | X | X | X | | -| mintReferenceTxInRedeemerValue | X | X | X | | -| requiredSignerHash | X | X | X | | -| txInCollateral | X | X | X | | -| changeAddress | X | X | X | Collateral return is not tested | -| invalidBefore | X | X | | | -| invalidHereafter | X | X | | | -| metadataValue | X | X | X | | -| signingKey | X | X | X | | -| complete | | | | TODO: EvaluateTx / Collateral returns | -| getUTxOInfo | X | X | X | | -| protocolParams | X | X | X | | - -## Other Tasks - -- Add collateral return -- Completing Apis - - Staking related apis - -## Higher Level refactor plan - -- UTxO selection -- Expose the `txBuilder` -- Migrating to lower level apis if any -- Removing redundant operations (make it using MeshTxBuilderCore's methods) diff --git a/packages/module/src/transaction/meshTxBuilder/type.ts b/packages/module/src/transaction/meshTxBuilder/type.ts index 65f75909d..cf951415d 100644 --- a/packages/module/src/transaction/meshTxBuilder/type.ts +++ b/packages/module/src/transaction/meshTxBuilder/type.ts @@ -5,6 +5,7 @@ import { LanguageVersion, PlutusScript, UTxO, + PoolParams, } from '@mesh/common/types'; export type MeshTxBuilderBody = { @@ -19,7 +20,7 @@ export type MeshTxBuilderBody = { changeAddress: string; metadata: Metadata[]; validityRange: ValidityRange; - // certificates?: Certificate[]; + certificates: Certificate[]; // withdrawals?: Record; signingKey: string[]; }; @@ -87,7 +88,7 @@ export type MintItem = { type: 'Plutus' | 'Native'; policyId: string; assetName: string; - amount: number; + amount: string; redeemer?: Redeemer; scriptSource?: | { @@ -135,6 +136,13 @@ export type Metadata = { metadata: object; }; +export type Certificate = + | { type: 'RegisterPool'; poolParams: PoolParams } + | { type: 'RegisterStake'; stakeKeyHash: string } + | { type: 'DelegateStake'; stakeKeyHash: string, poolId: string } + | { type: 'DeregisterStake'; stakeKeyHash: string } + | { type: 'RetirePool'; poolId: string; epoch: number }; + // Utilities export type RequiredWith = Required &