Skip to content
This repository has been archived by the owner on Sep 14, 2023. It is now read-only.

Commit

Permalink
north star dyn contract dx
Browse files Browse the repository at this point in the history
  • Loading branch information
harrysolovay committed Jan 31, 2023
1 parent 65a1485 commit b27d058
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 184 deletions.
184 changes: 27 additions & 157 deletions examples/ink_contract/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,168 +7,38 @@ const contract = client.inkContract({
metadataRaw: Deno.readTextFileSync("examples/ink_contract/metadata.json"),
})

const hash = await contract
const instance = contract
.instantiate({
code: Deno.readFileSync("examples/ink_contract/flipper.wasm"),
initiator: alice.publicKey,
})
.signed({ sender: alice })
.sent()
.logEvents()
.finalized()
.unwrapError()
.run()
.instance()

console.log(hash)

// class ExtrinsicFailed extends Error {
// override readonly name = "ExtrinsicFailedError"
// constructor(
// override readonly cause: {
// event?: Record<string, any>
// phase: { value: number }
// },
// ) {
// super()
// }
// }

// const tx = C.contracts.instantiate(client)({
// code,
// constructorMetadata,
// salt,
// sender: C.alice.address,
// }).signed(C.alice.sign)
// const finalizedIn = tx.watch(({ end }) => (status) => {
// console.log(status)
// if (typeof status !== "string" && (status.inBlock ?? status.finalized)) {
// return end(status.inBlock ?? status.finalized)
// } else if (C.rpc.known.TransactionStatus.isTerminal(status)) {
// return end(new Error())
// }
// return
// })
// const contractAddress = C.throwIfError(
// await C
// .events(tx, finalizedIn)
// .next((events) => {
// const extrinsicFailedEvent = events.find((e) =>
// e.event?.type === "System" && e.event?.value?.type === "ExtrinsicFailed"
// )
// if (extrinsicFailedEvent) {
// return new ExtrinsicFailed(extrinsicFailedEvent)
// }
// const event = events.find((e) =>
// e.event?.type === "Contracts" && e.event?.value?.type === "Instantiated"
// )
// return event?.event?.value.contract as Uint8Array
// })
// .run(),
// )

// const prefix = C.throwIfError(await C.const(client)("System", "SS58Prefix").access("value").run())
// console.log("Deployed Contract address", C.ss58.encode(prefix, contractAddress))

// const flipperContract = new C.fluent.Contract(client, metadata, contractAddress)
// console.log(
// ".get",
// await flipperContract.call({
// sender: C.alice.address,
// messageLabel: "get",
// args: [],
// }).run(),
// )
// console.log(
// "block hash and events",
// C.throwIfError(
// await flipperContract.callTx({
// sender: C.alice.address,
// args: [],
// sign: C.alice.sign,
// messageLabel: "flip",
// }).run(),
// )[0],
// )
// console.log(
// ".get",
// await flipperContract.call({
// sender: C.alice.address,
// messageLabel: "get",
// args: [],
// }).run(),
// )
// console.log(
// ".get_count",
// await flipperContract.call({ sender: C.alice.address, messageLabel: "get_count", args: [] })
// .run(),
// )
// console.log(
// ".inc block hash",
// C.throwIfError(
// await flipperContract.callTx({
// sender: C.alice.address,
// messageLabel: "inc",
// args: [],
// sign: C.alice.sign,
// }).run(),
// )[0],
// )
// console.log(
// ".inc block hash",
// C.throwIfError(
// await flipperContract.callTx({
// sender: C.alice.address,
// messageLabel: "inc",
// args: [],
// sign: C.alice.sign,
// }).run(),
// )[0],
// )
// console.log(
// ".get_count",
// await flipperContract.call({ sender: C.alice.address, messageLabel: "get_count", args: [] })
// .run(),
// )
// console.log(
// ".inc_by(3) block hash",
// C.throwIfError(
// await flipperContract.callTx({
// sender: C.alice.address,
// messageLabel: "inc_by",
// args: [3],
// sign: C.alice.sign,
// }).run(),
// )[0],
// )
// console.log(
// ".get_count",
// await flipperContract.call({ sender: C.alice.address, messageLabel: "get_count", args: [] })
// .run(),
// )
// console.log(
// ".inc_by_with_event(3) contract events",
// C.throwIfError(
// await flipperContract.callTx({
// sender: C.alice.address,
// messageLabel: "inc_by_with_event",
// args: [3],
// sign: C.alice.sign,
// }).run(),
// )[2],
// )
// console.log(
// ".method_returning_tuple(2,true)",
// await flipperContract.call({
// sender: C.alice.address,
// messageLabel: "method_returning_tuple",
// args: [2, true],
// }).run(),
// )
// console.log(
// ".method_returning_struct(3,false)",
// await flipperContract.call({
// sender: C.alice.address,
// messageLabel: "method_returning_struct",
// args: [3, false],
// }).run(),
// )
// TODO: what values do we want?
console.log(".get", await instance.msg("get").run())
console.log(".flip", await instance.msg("flip").signed({ sender: alice }).run())
console.log(".get", await instance.msg("get").run())
console.log(".get_count", await instance.msg("get_count").run())
console.log(".inc", await instance.msg("inc").signed({ sender: alice }).run())
console.log(".inc", await instance.msg("inc").signed({ sender: alice }).run())
console.log(".get_count", await instance.msg("get_count").signed({ sender: alice }).run())
console.log(
".inc_by(3)",
await instance.msg("inc_by", 3).signed({ sender: alice }).run(),
)
console.log(".get_count", await instance.msg("get_count").run())
console.log(
".inc_by_with_event(3) contract events",
await instance.msg("inc_by_with_event", 3).signed({ sender: alice }).run(),
)
console.log(
".method_returning_tuple(2,true)",
await instance.msg("method_returning_tuple", 2, true).signed({ sender: alice }).run(),
)
console.log(
".method_returning_struct(3,false)",
await instance.msg("method_returning_struct", 3, false).signed({ sender: alice }).run(),
)
45 changes: 39 additions & 6 deletions fluent/InkContract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ import { Rune, RunicArgs, ValueRune } from "../rune/mod.ts"
import { DeriveCodec } from "../scale_info/mod.ts"
import * as U from "../util/mod.ts"
import { ClientRune } from "./client.ts"
import { ExtrinsicRune } from "./extrinsic.ts"
import { ExtrinsicRune, SignedExtrinsicProps } from "./extrinsic.ts"
import { state } from "./rpc_known_methods.ts"

export interface InkContract {
metadataRaw: string
}

export interface InstantiateProps {
export interface InkContractInstantiateProps {
initiator: Uint8Array
code: Uint8Array
ctor?: string
Expand Down Expand Up @@ -49,7 +49,8 @@ export class InkContractRune<out U> extends Rune<InkContract, U> {
.unwrapError()
}

instantiate<X>(props: RunicArgs<X, InstantiateProps>) {
// TODO: create instantiation-specific rune so that we can `.address()` from it
instantiate<X>(props: RunicArgs<X, InkContractInstantiateProps>) {
const ctor = this.ctor(props.ctor)
const key = Rune.tuple([Rune.rec(props), ctor])
.map(([{ code, initiator }, ctor]) =>
Expand Down Expand Up @@ -90,11 +91,43 @@ export class InkContractRune<out U> extends Rune<InkContract, U> {
)
}

// call<X>(props: RunicArgs<X, {}>) {}
// callTx<X>(props: RunicArgs<X, {}>) {}
declare fromAddress: <X>(
...[address]: RunicArgs<X, [address: Uint8Array]>
) => InkContractInstanceRune<U>
}

export class InkContractInstanceRune<out U> extends Rune<Uint8Array, U> {}
export class InkContractInstanceRune<out U> extends Rune<Uint8Array, U> {
pallet

constructor(_prime: InkContractInstanceRune<U>["_prime"], readonly client: ClientRune<U>) {
super(_prime)
this.pallet = this.client.metadata().pallet("Contracts")
}

declare msg: <X>(
...[method, ...args]: RunicArgs<X, [method: string, ...args: unknown[]]>
) => InkContractMsg<U>
}

export class InkContractMsg<out U> extends Rune<Uint8Array, U> {
pallet

constructor(_prime: InkContractMsg<U>["_prime"], readonly client: ClientRune<U>) {
super(_prime)
this.pallet = this.client.metadata().pallet("Contracts")
}

declare signed: <X>(props: RunicArgs<X, SignedExtrinsicProps>) => InkContractMsgSigned<U>
}

export class InkContractMsgSigned<out U> extends Rune<Uint8Array, U> {
pallet

constructor(_prime: InkContractMsgSigned<U>["_prime"], readonly client: ClientRune<U>) {
super(_prime)
this.pallet = this.client.metadata().pallet("Contracts")
}
}

export class InkContractMetadataInvalidError extends Error {
override readonly name = "InkContractMetadataInvalidError"
Expand Down
21 changes: 0 additions & 21 deletions fluent/events.ts

This file was deleted.

17 changes: 17 additions & 0 deletions fluent/extrinsic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,22 @@ export class ExtrinsicStatusRune<out U1, out U2> extends Rune<Rune<TransactionSt
).as(ExtrinsicStatusRune)
}

// TODO: extract common logic to be shared between `inBlock` and `finalized`
// TODO: confirm this is correct / finalization is negligible
inBlock() {
return this.as(MetaRune).flatMap((events) =>
events
.as(ValueRune)
.filter(TransactionStatus.isTerminal)
.map((status) =>
typeof status !== "string" && (status.inBlock ?? status.finalized)
? (status.inBlock ?? status.finalized)
: new NeverInBlockError()
)
.singular()
).unwrapError()
}

finalized() {
return this.as(MetaRune).flatMap((events) =>
events
Expand All @@ -162,4 +178,5 @@ export class ExtrinsicStatusRune<out U1, out U2> extends Rune<Rune<TransactionSt
}
}

export class NeverInBlockError extends Error {}
export class NeverFinalizedError extends Error {}

0 comments on commit b27d058

Please sign in to comment.