Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transaction builder #34

Merged
merged 47 commits into from
Aug 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
b2b4f2f
Start designing the Tx building API
mpizenberg Jul 27, 2024
69f829d
Add a bit of documentation for Tx building
mpizenberg Jul 27, 2024
cfec3f7
Much progress on Tx building API
mpizenberg Jul 27, 2024
f1cbabc
Make some type improvements for tx building
mpizenberg Jul 28, 2024
b861f47
Add plutus mint/burn example
mpizenberg Jul 28, 2024
c7a8b60
Add send to plutus script example
mpizenberg Jul 28, 2024
a702364
Make some more progress with Tx building
mpizenberg Jul 28, 2024
830bcd9
Simpler phantom type for Tx (no record)
mpizenberg Jul 28, 2024
912ed96
Add temporary code for example 1
mpizenberg Jul 28, 2024
152b20f
Add temporary code for example 2
mpizenberg Jul 28, 2024
831e30c
Add temporary code for example 3
mpizenberg Jul 28, 2024
741973c
Add two forgotten phantom types
mpizenberg Jul 28, 2024
c6b5c07
Draft new API
mpizenberg Jul 31, 2024
1ab162d
Rewrote the whole Tx building
mpizenberg Aug 1, 2024
c7062dc
Rework of the Tx building code and example doc
mpizenberg Aug 4, 2024
22b988c
Fix exposing docs
mpizenberg Aug 4, 2024
1ec134d
Small renaming
mpizenberg Aug 4, 2024
8cb2ad1
Start work on Tx finalization
mpizenberg Aug 6, 2024
5cc1bd2
Check min ada in Tx outputs
mpizenberg Aug 7, 2024
cd88657
Keep output references in coin selection
mpizenberg Aug 7, 2024
db94cf2
Use Value instead of just ada in coin selection
mpizenberg Aug 7, 2024
17ab1bd
Remove old comments
mpizenberg Aug 7, 2024
561c633
Make coin selection work for multi asset
mpizenberg Aug 7, 2024
1cfea92
Done utxo selection in Tx finalization
mpizenberg Aug 7, 2024
6ca4f08
Extract coin selection into its own function
mpizenberg Aug 8, 2024
1761afe
Rename Balance into ProcessedIntents
mpizenberg Aug 8, 2024
f4ea643
Aggregates intents witnesses and redeemers
mpizenberg Aug 8, 2024
d3d045a
Perform coin selection per address
mpizenberg Aug 8, 2024
da33707
Add todos
mpizenberg Aug 8, 2024
a0c07f6
Using Utxo.RefDict for pre-selected inputs
mpizenberg Aug 8, 2024
7cbab43
Add AnyDict dependency to both examples
mpizenberg Aug 8, 2024
7f2e571
Move some doc warning todo
mpizenberg Aug 8, 2024
c43a67e
Simple field rename
mpizenberg Aug 8, 2024
8fe1e3b
Use a dict for withdrawals
mpizenberg Aug 9, 2024
cf6a42f
Accumulate pre-address selections
mpizenberg Aug 9, 2024
2f557be
Update inputs/outputs
mpizenberg Aug 9, 2024
df8520f
Add buildTx step
mpizenberg Aug 9, 2024
adaee64
Make progress with a txbuild example
mpizenberg Aug 9, 2024
6d51c36
Add forgotten freeOutput
mpizenberg Aug 9, 2024
237c6ee
Adjust global state for example tx 1
mpizenberg Aug 9, 2024
521ac48
Tiny pretty printing changes
mpizenberg Aug 10, 2024
48151f0
Fix example 2 and clean examples setup
mpizenberg Aug 10, 2024
688ab4d
Progress with pretty printing
mpizenberg Aug 10, 2024
141b968
Remove some debug logs
mpizenberg Aug 10, 2024
d262a51
Re-display example 1
mpizenberg Aug 10, 2024
aa1c60d
Complete example 3 with plutus script
mpizenberg Aug 10, 2024
28ae2e2
Adjust pretty print of datum
mpizenberg Aug 10, 2024
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
4 changes: 3 additions & 1 deletion elm.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"Bytes.Comparable",
"Bytes.Crc8",
"Bytes.Map",
"Cardano",
"Cardano.Address",
"Cardano.Cip30",
"Cardano.Cip67",
Expand All @@ -33,7 +34,8 @@
"elm/core": "1.0.5 <= v < 2.0.0",
"elm/json": "1.1.3 <= v < 2.0.0",
"elm-toulouse/cbor": "4.0.1 <= v < 5.0.0",
"jxxcarlson/hex": "4.0.0 <= v < 5.0.0"
"jxxcarlson/hex": "4.0.0 <= v < 5.0.0",
"turboMaCk/any-dict": "2.6.0 <= v < 3.0.0"
},
"test-dependencies": {
"elm-community/result-extra": "2.4.0 <= v < 3.0.0",
Expand Down
3 changes: 2 additions & 1 deletion examples/ogmios/elm.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"elm/html": "1.0.0",
"elm/json": "1.1.3",
"elm-toulouse/cbor": "4.0.1",
"jxxcarlson/hex": "4.0.0"
"jxxcarlson/hex": "4.0.0",
"turboMaCk/any-dict": "2.6.0"
},
"indirect": {
"elm/time": "1.0.0",
Expand Down
1 change: 1 addition & 0 deletions examples/txbuild/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
main.js
40 changes: 40 additions & 0 deletions examples/txbuild/Main.elm
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
module Main exposing (main)

import Browser
import Cardano
import Html exposing (Html, div, text)


main : Program () () ()
main =
Browser.element
{ init = \_ -> ( (), Cmd.none )
, update = \_ _ -> ( (), Cmd.none )
, subscriptions = \_ -> Sub.none
, view = view
}


example ex =
case ex () of
Err error ->
error

Ok tx ->
Cardano.prettyTx tx



-- VIEW


view : () -> Html ()
view _ =
div []
[ div [] [ text "Example transaction 1: send 1 ada from me to you" ]
, Html.pre [] [ text <| example Cardano.example1 ]
, div [] [ text "Example transaction 2: mint dog & burn 1 cat" ]
, Html.pre [] [ text <| example Cardano.example2 ]
, div [] [ text "Example transaction 3: spend 1 ada from a plutus script with 2 ada" ]
, Html.pre [] [ text <| example Cardano.example3 ]
]
3 changes: 3 additions & 0 deletions examples/txbuild/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```sh
npx elm-watch hot
```
84 changes: 84 additions & 0 deletions examples/txbuild/elm-cardano.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
function initElmCardanoJs(app) {
app.ports.toWallet.subscribe(async (value) => {
console.log("Received value destined to wallet:", value)
try {
if (value.requestType == "cip30-discover") {
const wallets = await concurrentHandleCip30Discover()
app.ports.fromWallet.send({responseType: "cip30-discover", wallets})
} else if (value.requestType == "cip30-enable") {
const {descriptor, api, walletHandle} = await enableCip30Wallet(value.id, value.extensions)
app.ports.fromWallet.send({responseType: "cip30-enable", descriptor, api, walletHandle})
} else if (value.requestType == "cip30-api") {
const apiResponse = await handleApiRequest(value)
app.ports.fromWallet.send(apiResponse)
}
} catch (error) {
app.ports.fromWallet.send({responseType: "cip30-error", error: error})
}
})

async function concurrentHandleCip30Discover() {
const wallets = []
if ("cardano" in window) {
const startTime = performance.now()
const walletsPromises = Object.keys(window.cardano).map(walletDescriptor)
const results = await Promise.allSettled(walletsPromises)
results.forEach(result => { if (result.status === 'fulfilled') {
wallets.push(result.value)
}});
const endTime = performance.now()
console.log(`Cardano CIP30 wallets discovered in ${endTime - startTime} ms:`, wallets)
} else {
console.log("Well there isn't any Cardano wallet here ^^")
}
return wallets
}

async function walletDescriptor(walletId) {
const startTime = performance.now()
const wallet = window.cardano[walletId]
for (const key of ["name", "icon", "apiVersion", "isEnabled"]) {
if (!(key in wallet)) throw new Error(`Missing expected key in wallet '${walletId}': ${key}`)
}
const descriptor = {
id : walletId,
name : wallet.name,
icon : wallet.icon,
apiVersion : wallet.apiVersion,
supportedExtensions : wallet.supportedExtensions || [],
isEnabled : await wallet.isEnabled(),
}
const endTime = performance.now()
console.log(`${walletId} discovered in ${endTime - startTime} ms:`)
return descriptor
}

async function enableCip30Wallet(walletId, extensionsIds) {
const extensions = extensionsIds.map((cipId) => ({cip: cipId}))
if (walletId in window.cardano) {
const walletHandle = window.cardano[walletId]
// const api = await walletHandle.enable({extensions}) // Eternl incorrect handle of CIP30 enable
const api = await walletHandle.enable(extensions) // Eternl incorrect handle of CIP30 enable
const descriptor = await walletDescriptor(walletId)
return {descriptor, api, walletHandle}
} else {
throw new Error("Wallet ID does not correspond to any installed wallet: " + walletId)
}
}

async function handleApiRequest({id, api, method, args}) {
if (id in window.cardano) {
// Replace "null" by "undefined" in the args array
correctArgs = args.map(item => item === null ? undefined : item)
const response = await api[method](...correctArgs)
return {
responseType: "cip30-api",
walletId: id,
method,
response,
}
} else {
throw new Error("Wallet ID does not correspond to any installed wallet: " + walletId)
}
}
}
11 changes: 11 additions & 0 deletions examples/txbuild/elm-watch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"serve": ".",
"targets": {
"main": {
"inputs": [
"Main.elm"
],
"output": "main.js"
}
}
}
33 changes: 33 additions & 0 deletions examples/txbuild/elm.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"type": "application",
"source-directories": [
".",
"../../src"
],
"elm-version": "0.19.1",
"dependencies": {
"direct": {
"dwayne/elm-integer": "1.0.0",
"dwayne/elm-natural": "1.1.1",
"elm/browser": "1.0.2",
"elm/bytes": "1.0.8",
"elm/core": "1.0.5",
"elm/html": "1.0.0",
"elm/json": "1.1.3",
"elm-toulouse/cbor": "4.0.1",
"jxxcarlson/hex": "4.0.0",
"turboMaCk/any-dict": "2.6.0"
},
"indirect": {
"elm/time": "1.0.0",
"elm/url": "1.0.0",
"elm/virtual-dom": "1.0.3",
"elm-community/list-extra": "8.7.0",
"elm-toulouse/float16": "1.0.1"
}
},
"test-dependencies": {
"direct": {},
"indirect": {}
}
}
19 changes: 19 additions & 0 deletions examples/txbuild/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<html>
<head>
<meta charset="UTF-8" />
<title>Main</title>
<script src="main.js"></script>
<script src="elm-cardano.js"></script>
</head>

<body>
<div id="myapp"></div>
<script>
var app = Elm.Main.init({
node: document.getElementById("myapp"),
flags: null,
});
// initElmCardanoJs(app)
</script>
</body>
</html>
3 changes: 2 additions & 1 deletion examples/wallet-cip30/elm.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"elm/html": "1.0.0",
"elm/json": "1.1.3",
"elm-toulouse/cbor": "4.0.1",
"jxxcarlson/hex": "4.0.0"
"jxxcarlson/hex": "4.0.0",
"turboMaCk/any-dict": "2.6.0"
},
"indirect": {
"elm/time": "1.0.0",
Expand Down
26 changes: 22 additions & 4 deletions src/Bytes/Comparable.elm
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,21 @@ module Bytes.Comparable exposing
( Bytes
, Any, toAny
, chunksOf, width, isEmpty
, bytes, fromBytes, fromString, fromStringUnchecked
, toBytes, toString, toCbor, toU8
, bytes, fromBytes, fromString, fromStringUnchecked, fromText
, toBytes, toString, toText, toCbor, toU8
)

{-| Comparable Bytes

-- TODO: Because we rely on the sorting of the hex string,
-- it is super important to check that we only use
-- lower case OR upper case letters, but no mix

@docs Bytes
@docs Any, toAny
@docs chunksOf, width, isEmpty
@docs bytes, fromBytes, fromString, fromStringUnchecked
@docs toBytes, toString, toCbor, toU8
@docs bytes, fromBytes, fromString, fromStringUnchecked, fromText
@docs toBytes, toString, toText, toCbor, toU8

-}

Expand Down Expand Up @@ -82,6 +86,13 @@ fromStringUnchecked =
Bytes


{-| Create a [Bytes] with some text encoded as UTF8.
-}
fromText : String -> Bytes a
fromText str =
E.encode (E.string str) |> fromBytes


{-| Create a [Bytes] object from an elm/bytes [Bytes.Bytes].
-}
fromBytes : Bytes.Bytes -> Bytes a
Expand All @@ -96,6 +107,13 @@ toString (Bytes str) =
str


{-| Convert [Bytes] into a UTF8 String.
-}
toText : Bytes a -> Maybe String
toText bs =
D.decode (D.string <| width bs) (toBytes bs)


{-| Convert [Bytes] into elm/bytes [Bytes.Bytes].
-}
toBytes : Bytes a -> Bytes.Bytes
Expand Down
Loading
Loading