Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@
"lint": "next lint"
},
"dependencies": {
"@cashscript/utils": "^0.13.1",
"@cashscript/utils": "^0.14.0-next.0",
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.0",
"@monaco-editor/react": "^4.7.0",
"bootstrap": "^5.3.7",
"cashc": "^0.13.1",
"cashc": "^0.14.0-next.0",
"cashc-v0.12": "npm:cashc@^0.12.2",
"cashscript": "^0.13.1",
"cashscript": "^0.14.0-next.0",
"next": "15.5.9",
"react": "18.2.0",
"react-bootstrap": "^2.10.10",
Expand Down
2 changes: 1 addition & 1 deletion src/components/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ const Editor: React.FC<Props> = ({ code, setCode, compile, compilerVersion, setC
onChange={(e) => setCompilerVersion(e.target.value as CashScriptVersion)}
style={{ width: '170px', borderRadius: '30px' }}
>
<option value="0.13">cashc v0.13</option>
<option value="0.14">cashc v0.14</option>
<option value="0.12">cashc v0.12</option>
</Form.Select>
<Button
Expand Down
10 changes: 5 additions & 5 deletions src/components/Main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const Main: React.FC<Props> = ({
}) => {

const [initializeContracts, setInitializeContracts] = useState<0 | 1 | 2>(0);
const [compilerVersion, setCompilerVersion] = useState<CashScriptVersion>('0.13');
const [compilerVersion, setCompilerVersion] = useState<CashScriptVersion>('0.14');

useEffect(() => {
const codeLocalStorage = localStorage.getItem("code");
Expand All @@ -44,10 +44,10 @@ const Main: React.FC<Props> = ({
} else {
// add default example contracts to local storage
try {
const artifactExampleTimeout = compileCashScript(exampleTimeoutContract, '0.13')
const artifactExampleEscrow = compileCashScript(exampleEscrowContract, '0.13')
const artifactExampleStramingMecenas = compileCashScript(exampleStramingMecenasContract, '0.13')
const artifactExampleDex = compileCashScript(exampleDexContract, '0.13')
const artifactExampleTimeout = compileCashScript(exampleTimeoutContract, '0.14')
const artifactExampleEscrow = compileCashScript(exampleEscrowContract, '0.14')
const artifactExampleStramingMecenas = compileCashScript(exampleStramingMecenasContract, '0.14')
const artifactExampleDex = compileCashScript(exampleDexContract, '0.14')
const defaultArtifacts = [artifactExampleTimeout, artifactExampleEscrow, artifactExampleStramingMecenas, artifactExampleDex]
setArtifacts(defaultArtifacts)
localStorage.setItem("artifacts", JSON.stringify(defaultArtifacts, null, 2));
Expand Down
82 changes: 57 additions & 25 deletions src/components/TransactionBuilder.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, {useState} from 'react'
import React, {useState, useCallback, useMemo} from 'react'
import { NetworkProvider, Output, SignatureTemplate, TransactionBuilder, Unlocker } from 'cashscript'
import { Wallet, ContractInfo, ExplorerString, ContractUtxo, WalletUtxo } from './shared'
import { Button, Card, Form } from 'react-bootstrap'
Expand Down Expand Up @@ -48,32 +48,51 @@ const TransactionBuilderPage: React.FC<Props> = ({ provider, wallets, contracts,
setInputs(inputsCopy)
}

async function sendTransaction() {
// try to send transaction and alert result
// Construct a TransactionBuilder from the current inputs, outputs and options.
// Shared by sendTransaction and the live fee calculation. Throws if the
// transaction is incomplete (e.g. an undefined input or missing unlocker).
const buildTransaction = useCallback(() => {
// start constructing transaction
const transaction = new TransactionBuilder({
provider,
allowImplicitFungibleTokenBurn,
...(enableMaxFeeSatoshis && maximumFeeSatoshis ? { maximumFeeSatoshis: BigInt(maximumFeeSatoshis) } : {}),
...(enableMaxFeeSatsPerByte && maximumFeeSatsPerByte ? { maximumFeeSatsPerByte: Number(maximumFeeSatsPerByte) } : {}),
})

// add inputs to transaction in the user-defined order
inputs.forEach((input, inputIndex) => {
if(!input) throw new Error("Undefined input provided")
if('walletIndex' in input){
const walletIndex = input.walletIndex
const sigTemplate = new SignatureTemplate(wallets[walletIndex].privKey)
transaction.addInput(input, sigTemplate.unlockP2PKH())
} else {
const inputUnlocker = inputUnlockers[inputIndex]
if(!inputUnlocker) throw new Error("Missing unlocker for input")
transaction.addInput(input, inputUnlocker)
}
})

transaction.addOutputs(outputs)
if(enableLocktime) transaction.setLocktime(Number(locktime))
return transaction
}, [provider, wallets, allowImplicitFungibleTokenBurn, enableMaxFeeSatoshis, maximumFeeSatoshis, enableMaxFeeSatsPerByte, maximumFeeSatsPerByte, inputs, inputUnlockers, outputs, enableLocktime, locktime])

// Reactively calculate the transaction fee and fee rate as the user edits the
// inputs/outputs. Returns null while the transaction can't yet be built.
const feeData = useMemo(() => {
try {
// start constructing transaction
const transaction = new TransactionBuilder({
provider,
allowImplicitFungibleTokenBurn,
...(enableMaxFeeSatoshis && maximumFeeSatoshis ? { maximumFeeSatoshis: BigInt(maximumFeeSatoshis) } : {}),
...(enableMaxFeeSatsPerByte && maximumFeeSatsPerByte ? { maximumFeeSatsPerByte: Number(maximumFeeSatsPerByte) } : {}),
})

// add inputs to transaction in the user-defined order
inputs.forEach((input, inputIndex) => {
if(!input) throw new Error("Undefined input provided")
if('walletIndex' in input){
const walletIndex = input.walletIndex
const sigTemplate = new SignatureTemplate(wallets[walletIndex].privKey)
transaction.addInput(input, sigTemplate.unlockP2PKH())
} else {
const inputUnlocker = inputUnlockers[inputIndex]
transaction.addInput(input, inputUnlocker)
}
})
return buildTransaction().calculateTransactionFee()
} catch {
return null
}
}, [buildTransaction])

transaction.addOutputs(outputs)
if(enableLocktime) transaction.setLocktime(Number(locktime))
async function sendTransaction() {
// try to send transaction and alert result
try {
const transaction = buildTransaction()

// check for mocknet
if(provider.network == "mocknet"){
Expand Down Expand Up @@ -205,6 +224,19 @@ const TransactionBuilderPage: React.FC<Props> = ({ provider, wallets, contracts,
</Form>
</details>

<div style={{ marginBottom: '10px' }}>
{feeData ? (
<span>
Calculated fee: <strong>{feeData.feeSats.toString()} sats</strong>
{' '}(<strong>{feeData.feeSatsPerByte.toFixed(2)} sats/byte</strong>)
</span>
) : (
<span style={{ color: '#888' }}>
Calculated fee: add valid inputs and outputs to calculate the fee
</span>
)}
</div>

<Button variant="secondary" style={{ display: "block" }} size="sm" onClick={sendTransaction}>
{ provider.network === "mocknet" ? "Evaluate" : "Send" }
</Button>
Expand Down
2 changes: 1 addition & 1 deletion src/editor/cashscript/diagnostics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export interface CashScriptDiagnostic {
}

const compileStringByVersion: Record<CashScriptVersion, CompileStringWithErrorListener> = {
'0.13': compileString,
'0.14': compileString,
'0.12': compileStringV012,
};

Expand Down
4 changes: 2 additions & 2 deletions src/editor/cashscript/version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
// versions, which avoids re-registering providers (Monaco can't cleanly
// unregister them) while still gating version-specific language features.

export type CashScriptVersion = '0.12' | '0.13';
export type CashScriptVersion = '0.12' | '0.14';

let currentVersion: CashScriptVersion = '0.13';
let currentVersion: CashScriptVersion = '0.14';

// Listeners notified when the selected version changes. Used by the highlighting
// layer, which (unlike completions/hover) is registered statically and must be
Expand Down
28 changes: 14 additions & 14 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,10 @@
dependencies:
"@bitauth/libauth" "^3.1.0-next.8"

"@cashscript/utils@^0.13.1":
version "0.13.1"
resolved "https://registry.yarnpkg.com/@cashscript/utils/-/utils-0.13.1.tgz#cfcfcf7c6a8edb41f4c3887b908592147c9a3736"
integrity sha512-MAZ0SK+wvgQbTKHHgTDocfOI+Yrmw5c8bv4FyKUuCtjw/+JE/HJEEKyL/0ppEFbOzv5Jy4JQIV6n7GPNWm/wbQ==
"@cashscript/utils@^0.14.0-next.0":
version "0.14.0-next.0"
resolved "https://registry.yarnpkg.com/@cashscript/utils/-/utils-0.14.0-next.0.tgz#9e9ea4cd72875d5e9ddbf46b2ea016cc913c6882"
integrity sha512-N0LQE2Tf63NWMeuk/bflyBbgLYBOMu8x1L8qbWDY6RaygUAz5qNTel/5ZoAyyZ6yAFanrtPL27OvLDbyTlj7Xw==
dependencies:
"@bitauth/libauth" "^3.1.0-next.8"

Expand Down Expand Up @@ -1200,24 +1200,24 @@ caniuse-lite@^1.0.30001579:
commander "^14.0.0"
semver "^7.7.2"

cashc@^0.13.1:
version "0.13.1"
resolved "https://registry.yarnpkg.com/cashc/-/cashc-0.13.1.tgz#9b246f2997eda2fbe5c358fdedbb36bdc57b5a96"
integrity sha512-u0tcMNyK29FOLhVzoQsynmd51QtAGxPIpy8pScLu18RV1MMI0WD1YJY1DBtRNaQlOupeBeO24O6lTNoJ621d2w==
cashc@^0.14.0-next.0:
version "0.14.0-next.0"
resolved "https://registry.yarnpkg.com/cashc/-/cashc-0.14.0-next.0.tgz#20b3d57da50036d5f3430c40d7b1fcd58bc2f827"
integrity sha512-JLsKsi4Zk/KbTszdLVUFFSta7VgdEk0UHoAx7ugGREtDQFsXcR+JN/yGihuO3BmcTqyKDe9P/GDva5CMhOQJ0Q==
dependencies:
"@bitauth/libauth" "^3.1.0-next.8"
"@cashscript/utils" "^0.13.1"
"@cashscript/utils" "^0.14.0-next.0"
antlr4 "^4.13.2"
commander "^14.0.0"
semver "^7.7.2"

cashscript@^0.13.1:
version "0.13.1"
resolved "https://registry.yarnpkg.com/cashscript/-/cashscript-0.13.1.tgz#06059881922c35064347e13d97eeb0eb057eea3f"
integrity sha512-BrPFO4TYFTFc41Ft4Hpsky9UNct2SEv6QdC89utu4B/9+8kl4uJLy4SjUv9ZJciGSigQOg4McKYzuYCc/oYl2g==
cashscript@^0.14.0-next.0:
version "0.14.0-next.0"
resolved "https://registry.yarnpkg.com/cashscript/-/cashscript-0.14.0-next.0.tgz#8e48bdb45761bac03460950f2a678a9a8c0c732a"
integrity sha512-s6DQ8cA5Z23c/HU2tKcFvKyYp6Q95Ppa1c+p0NCPosBSy/hggkRPfDk5aBOCzpx0WG1K19ip9peAcZcXIg4zIA==
dependencies:
"@bitauth/libauth" "^3.1.0-next.8"
"@cashscript/utils" "^0.13.1"
"@cashscript/utils" "^0.14.0-next.0"
"@electrum-cash/network" "^4.1.3"
fflate "^0.8.2"
semver "^7.7.2"
Expand Down