-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1258 from demergent-labs/functional_syntax_compos…
…ite_queries Functional syntax composite queries
- Loading branch information
Showing
20 changed files
with
415 additions
and
554 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,12 @@ | ||
import { blob, ic, query, Service, text } from 'azle'; | ||
|
||
export default class extends Service { | ||
export default Service({ | ||
// encodes a Candid string to Candid bytes | ||
@query([text], blob) | ||
candidEncode(candidString: text): blob { | ||
candidEncode: query([text], blob, (candidString) => { | ||
return ic.candidEncode(candidString); | ||
} | ||
|
||
}), | ||
// decodes Candid bytes to a Candid string | ||
@query([blob], text) | ||
candidDecode(candidEncoded: blob): text { | ||
candidDecode: query([blob], text, (candidEncoded) => { | ||
return ic.candidDecode(candidEncoded); | ||
} | ||
} | ||
}) | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +1,20 @@ | ||
import { | ||
candid, | ||
init, | ||
Opt, | ||
query, | ||
Record, | ||
Service, | ||
text, | ||
Tuple, | ||
Void | ||
} from 'azle'; | ||
import { init, Opt, query, Record, Service, text, Tuple } from 'azle'; | ||
|
||
class User extends Record { | ||
@candid(text) | ||
id: text; | ||
} | ||
const User = Record({ | ||
id: text | ||
}); | ||
|
||
export default class extends Service { | ||
greeting: text = 'Hello User'; | ||
user: Opt<User> = []; | ||
let greeting: text = 'Hello User'; | ||
let user: Opt<typeof User> = []; | ||
|
||
@init([Tuple(text, User)]) | ||
init(tuple: Tuple<[string, User]>): Void { | ||
this.greeting = tuple[0]; | ||
this.user = [tuple[1]]; | ||
} | ||
|
||
@query([], text) | ||
greetUser(): text { | ||
return `${this.greeting} ${this.user[0]?.id ?? '??'}`; | ||
} | ||
} | ||
// TODO tuple types aren't done, they don't have TypeScript types | ||
export default Service({ | ||
init: init([Tuple(text, User)], (tuple) => { | ||
greeting = tuple[0]; | ||
user = [tuple[1]]; | ||
return undefined; | ||
}), | ||
greetUser: query([], text, () => { | ||
return `${greeting} ${user[0]?.id ?? '??'}`; | ||
}) | ||
}); |
141 changes: 72 additions & 69 deletions
141
examples/composite_queries/canisters/canister1/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,89 +1,92 @@ | ||
import { ic, Manual, nat, Principal, query, Service, text, update } from 'azle'; | ||
import { | ||
ic, | ||
init, | ||
Manual, | ||
nat, | ||
Principal, | ||
query, | ||
Service, | ||
text, | ||
update | ||
} from 'azle'; | ||
import Canister2 from '../canister2'; | ||
|
||
class Canister1 extends Service { | ||
canister2 = new Canister2( | ||
Principal.fromText( | ||
process.env.CANISTER2_PRINCIPAL ?? | ||
ic.trap('process.env.CANISTER2_PRINCIPAL is undefined') | ||
) | ||
); | ||
let canister2: typeof Canister2; | ||
let counter: nat = 0n; | ||
|
||
counter: nat = 0n; | ||
const incCounter = query([], nat, async () => { | ||
counter += 1n; | ||
|
||
// Composite query calling a query | ||
@query([], text) | ||
async simpleCompositeQuery(): Promise<text> { | ||
return await ic.call(this.canister2.simpleQuery); | ||
} | ||
return counter; | ||
}); | ||
|
||
const service = Service({ | ||
init: init([], () => { | ||
canister2 = Canister2( | ||
Principal.fromText( | ||
process.env.CANISTER2_PRINCIPAL ?? | ||
ic.trap('process.env.CANISTER2_PRINCIPAL is undefined') | ||
) | ||
); | ||
}), | ||
// Composite query calling a query | ||
simpleCompositeQuery: query([], text, async () => { | ||
return await ic.call(canister2.simpleQuery); | ||
}), | ||
// Composite query calling a manual query | ||
@query([], text) | ||
async manualQuery(): Promise<text> { | ||
return await ic.call(this.canister2.manualQuery); | ||
} | ||
|
||
manualQuery: query([], text, async () => { | ||
return (await ic.call(canister2.manualQuery)) as unknown as string; // TODO is this the best we can do for the types in this situation? | ||
}), | ||
// Manual composite query calling a manual query | ||
@query([], text, { manual: true }) | ||
async totallyManualQuery(): Promise<Manual<text>> { | ||
ic.reply(await ic.call(this.canister2.manualQuery), text); | ||
} | ||
|
||
totallyManualQuery: query( | ||
[], | ||
Manual(text), | ||
async () => { | ||
ic.reply(await ic.call(canister2.manualQuery), text); | ||
}, | ||
{ manual: true } | ||
), | ||
// Composite query calling another composite query | ||
@query([], text) | ||
async deepQuery(): Promise<text> { | ||
return await ic.call(this.canister2.deepQuery); | ||
} | ||
|
||
deepQuery: query([], text, async () => { | ||
return await ic.call(canister2.deepQuery); | ||
}), | ||
// Composite query calling an update method. SHOULDN'T WORK | ||
@query([], text) | ||
async updateQuery(): Promise<text> { | ||
return await ic.call(this.canister2.updateQuery); | ||
} | ||
|
||
updateQuery: query([], text, async () => { | ||
return await ic.call(canister2.updateQuery); | ||
}), | ||
// Composite query being called by a query method. SHOULDN'T WORK | ||
@query([], text) | ||
async simpleQuery(): Promise<text> { | ||
return await ic.call(this.canister2.simpleQuery); | ||
} | ||
|
||
simpleQuery: query([], text, async () => { | ||
return await ic.call(canister2.simpleQuery); | ||
}), | ||
// Composite query being called by an update method. SHOULDN'T WORK | ||
@update([], text) | ||
async simpleUpdate(): Promise<text> { | ||
return await ic.call(this.canister2.deepQuery); | ||
} | ||
|
||
simpleUpdate: update([], text, async () => { | ||
return await ic.call(canister2.deepQuery); | ||
}), | ||
// Composite query that modifies the state. Should revert after the call is done | ||
@query([], nat) | ||
async incCounter(): Promise<nat> { | ||
this.counter += 1n; | ||
|
||
return this.counter; | ||
} | ||
|
||
incCounter, | ||
// Composite query calling queries on the same canister | ||
@query([], nat) | ||
async incCanister1(): Promise<nat> { | ||
this.counter += 1n; | ||
|
||
const canister1AResult = await ic.call(this.incCounter); | ||
incCanister1: query([], nat, async () => { | ||
// TODO This is not an ideal solution but will work for now | ||
const self = Service({ | ||
incCounter | ||
})(ic.id()); | ||
|
||
const canister1BResult = await ic.call(this.incCounter); | ||
counter += 1n; | ||
|
||
return this.counter + canister1AResult + canister1BResult; | ||
} | ||
const canister1AResult = await ic.call(self.incCounter); | ||
const canister1BResult = await ic.call(self.incCounter); | ||
|
||
return counter + canister1AResult + canister1BResult; | ||
}), | ||
// Composite query calling queries that modify the state | ||
@query([], nat) | ||
async incCanister2(): Promise<nat> { | ||
this.counter += 1n; | ||
|
||
const canister2AResult = await ic.call(this.canister2.incCounter); | ||
incCanister2: query([], nat, async () => { | ||
counter += 1n; | ||
|
||
const canister2BResult = await ic.call(this.canister2.incCounter); | ||
const canister2AResult = await ic.call(canister2.incCounter); | ||
const canister2BResult = await ic.call(canister2.incCounter); | ||
|
||
return this.counter + canister2AResult + canister2BResult; | ||
} | ||
} | ||
return counter + canister2AResult + canister2BResult; | ||
}) | ||
}); | ||
|
||
export default Canister1; | ||
export default service; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,40 +1,48 @@ | ||
import { ic, Manual, nat, Principal, query, Service, text, update } from 'azle'; | ||
import { | ||
ic, | ||
init, | ||
Manual, | ||
nat, | ||
Principal, | ||
query, | ||
Service, | ||
text, | ||
update | ||
} from 'azle'; | ||
import Canister3 from '../canister3'; | ||
|
||
export default class extends Service { | ||
canister3 = new Canister3( | ||
Principal.fromText( | ||
process.env.CANISTER3_PRINCIPAL ?? | ||
ic.trap('process.env.CANISTER3_PRINCIPAL is undefined') | ||
) | ||
); | ||
|
||
counter: nat = 0n; | ||
let canister3: typeof Canister3; | ||
let counter: nat = 0n; | ||
|
||
export default Service({ | ||
init: init([], () => { | ||
canister3 = Canister3( | ||
Principal.fromText( | ||
process.env.CANISTER3_PRINCIPAL ?? | ||
ic.trap('process.env.CANISTER3_PRINCIPAL is undefined') | ||
) | ||
); | ||
}), | ||
// TODO is this supposed to be a query? | ||
@query([], nat) | ||
async incCounter(): Promise<nat> { | ||
this.counter += 1n; | ||
return this.counter; | ||
} | ||
|
||
@query([], text) | ||
simpleQuery(): text { | ||
incCounter: query([], nat, () => { | ||
counter += 1n; | ||
return counter; | ||
}), | ||
simpleQuery: query([], text, () => { | ||
return 'Hello from Canister 2'; | ||
} | ||
|
||
@update([], text) | ||
updateQuery(): text { | ||
}), | ||
updateQuery: update([], text, () => { | ||
return 'Hello from a Canister 2 update'; | ||
} | ||
|
||
@query([], text, { manual: true }) | ||
manualQuery(): Manual<text> { | ||
ic.reply('Hello from Canister 2 manual query', text); | ||
} | ||
|
||
@query([], text) | ||
async deepQuery(): Promise<text> { | ||
return await ic.call(this.canister3.deepQuery); | ||
} | ||
} | ||
}), | ||
manualQuery: query( | ||
[], | ||
Manual(text), | ||
() => { | ||
ic.reply('Hello from Canister 2 manual query', text); | ||
}, | ||
{ manual: true } | ||
), | ||
deepQuery: query([], text, async () => { | ||
return await ic.call(canister3.deepQuery); | ||
}) | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,7 @@ | ||
import { Service, query, text } from 'azle'; | ||
import { query, Service, text } from 'azle'; | ||
|
||
export default class extends Service { | ||
@query([], text) | ||
deepQuery(): text { | ||
export default Service({ | ||
deepQuery: query([], text, () => { | ||
return 'Hello from Canister 3'; | ||
} | ||
} | ||
}) | ||
}); |
Oops, something went wrong.