-
Notifications
You must be signed in to change notification settings - Fork 115
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: implicit init function if not present (#167)
- Loading branch information
Showing
19 changed files
with
1,884 additions
and
9 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
109 changes: 109 additions & 0 deletions
109
src/test/__snapshots__/feature-implicit-init.spec.ts.snap
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 |
---|---|---|
@@ -0,0 +1,109 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`feature-send should deploy 1`] = ` | ||
[ | ||
{ | ||
"$seq": 0, | ||
"events": [ | ||
{ | ||
"$type": "deploy", | ||
}, | ||
{ | ||
"$type": "received", | ||
"message": { | ||
"body": { | ||
"type": "known", | ||
"value": { | ||
"$$type": "Deploy", | ||
"queryId": 0n, | ||
}, | ||
}, | ||
"bounce": true, | ||
"from": "@treasure(treasure)", | ||
"to": "kQDHqMJCGk6QhukOD8ZKGLou9KVeRAM3pGOa_JYP47mob9WO", | ||
"type": "internal", | ||
"value": "1", | ||
}, | ||
}, | ||
{ | ||
"$type": "processed", | ||
"gasUsed": 7147n, | ||
}, | ||
{ | ||
"$type": "sent", | ||
"messages": [ | ||
{ | ||
"body": { | ||
"type": "known", | ||
"value": { | ||
"$$type": "DeployOk", | ||
"queryId": 0n, | ||
}, | ||
}, | ||
"bounce": false, | ||
"from": "kQDHqMJCGk6QhukOD8ZKGLou9KVeRAM3pGOa_JYP47mob9WO", | ||
"to": "@treasure(treasure)", | ||
"type": "internal", | ||
"value": "0.991657", | ||
}, | ||
], | ||
}, | ||
], | ||
}, | ||
] | ||
`; | ||
|
||
exports[`feature-send should increment counter 1`] = ` | ||
[ | ||
{ | ||
"$seq": 1, | ||
"events": [ | ||
{ | ||
"$type": "received", | ||
"message": { | ||
"body": { | ||
"text": "increment", | ||
"type": "text", | ||
}, | ||
"bounce": true, | ||
"from": "@treasure(treasure)", | ||
"to": "kQDHqMJCGk6QhukOD8ZKGLou9KVeRAM3pGOa_JYP47mob9WO", | ||
"type": "internal", | ||
"value": "1", | ||
}, | ||
}, | ||
{ | ||
"$type": "processed", | ||
"gasUsed": 3746n, | ||
}, | ||
], | ||
}, | ||
{ | ||
"$seq": 2, | ||
"events": [ | ||
{ | ||
"$type": "storage-charged", | ||
"amount": "0.000000004", | ||
}, | ||
{ | ||
"$type": "received", | ||
"message": { | ||
"body": { | ||
"text": "increment", | ||
"type": "text", | ||
}, | ||
"bounce": true, | ||
"from": "@treasure(treasure)", | ||
"to": "kQDHqMJCGk6QhukOD8ZKGLou9KVeRAM3pGOa_JYP47mob9WO", | ||
"type": "internal", | ||
"value": "1", | ||
}, | ||
}, | ||
{ | ||
"$type": "processed", | ||
"gasUsed": 3746n, | ||
}, | ||
], | ||
}, | ||
] | ||
`; |
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 |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import { toNano } from '@ton/core'; | ||
import { ContractSystem } from '@tact-lang/emulator'; | ||
import { __DANGER_resetNodeId } from '../grammar/ast'; | ||
import { MyContract } from './features/output/implicit-init_MyContract'; | ||
import { run } from '../node'; | ||
import { consoleLogger } from '../logger'; | ||
|
||
describe('feature-send', () => { | ||
beforeAll(() => { | ||
jest.spyOn(consoleLogger, 'error').mockImplementation(() => {}); | ||
}); | ||
|
||
beforeEach(() => { | ||
__DANGER_resetNodeId(); | ||
}); | ||
|
||
afterAll(() => { | ||
(consoleLogger.error as jest.Mock).mockRestore(); | ||
}); | ||
|
||
afterEach(() => { | ||
(consoleLogger.error as jest.Mock).mockClear(); | ||
}); | ||
|
||
it('should deploy', async () => { | ||
// Init | ||
const system = await ContractSystem.create(); | ||
const treasure = system.treasure('treasure'); | ||
const contract = system.open(await MyContract.fromInit()); | ||
const tracker = system.track(contract.address); | ||
await contract.send( | ||
treasure, | ||
{ value: toNano('1') }, | ||
{ $$type: 'Deploy', queryId: 0n } | ||
); | ||
await system.run(); | ||
expect(await contract.getGetCounter()).toBe(0n); | ||
expect(tracker.collect()).toMatchSnapshot(); | ||
}); | ||
|
||
it('should increment counter', async () => { | ||
// Init | ||
const system = await ContractSystem.create(); | ||
const treasure = system.treasure('treasure'); | ||
const contract = system.open(await MyContract.fromInit()); | ||
await contract.send( | ||
treasure, | ||
{ value: toNano('1') }, | ||
{ $$type: 'Deploy', queryId: 0n } | ||
); | ||
await system.run(); | ||
|
||
// Test | ||
expect(await contract.getGetCounter()).toBe(0n); | ||
const tracker = system.track(contract); | ||
await contract.send(treasure, { value: toNano('1') }, 'increment'); | ||
await system.run(); | ||
expect(await contract.getGetCounter()).toBe(1n); | ||
await contract.send(treasure, { value: toNano('1') }, 'increment'); | ||
await system.run(); | ||
expect(await contract.getGetCounter()).toBe(2n); | ||
expect(tracker.collect()).toMatchSnapshot(); | ||
}); | ||
|
||
it('should not compile with uninitialized storage fields', async () => { | ||
const result = await run({ | ||
configPath: __dirname + '/test-tact.config.json', | ||
projectNames: ['implicit-init-2'], | ||
}); | ||
expect((consoleLogger.error as jest.Mock).mock.lastCall[0]).toContain( | ||
'Field test_field is not set' | ||
); | ||
expect(result).toBe(false); | ||
}); | ||
}); |
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 |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import "@stdlib/deploy"; | ||
|
||
contract MyContract with Deployable { | ||
counter: Int = 0; | ||
test_field: Int; | ||
|
||
receive("increment") { | ||
self.counter += 1; | ||
} | ||
|
||
get fun getCounter(): Int { | ||
return self.counter; | ||
} | ||
|
||
get fun getTestField(): Int { | ||
return self.test_field; | ||
} | ||
} |
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 |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import "@stdlib/deploy"; | ||
|
||
contract MyContract with Deployable { | ||
counter: Int = 0; | ||
|
||
receive("increment") { | ||
self.counter += 1; | ||
} | ||
|
||
get fun getCounter(): Int { | ||
return self.counter; | ||
} | ||
} |
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 |
---|---|---|
@@ -0,0 +1 @@ | ||
{"name":"MyContract","types":[{"name":"StateInit","header":null,"fields":[{"name":"code","type":{"kind":"simple","type":"cell","optional":false}},{"name":"data","type":{"kind":"simple","type":"cell","optional":false}}]},{"name":"Context","header":null,"fields":[{"name":"bounced","type":{"kind":"simple","type":"bool","optional":false}},{"name":"sender","type":{"kind":"simple","type":"address","optional":false}},{"name":"value","type":{"kind":"simple","type":"int","optional":false,"format":257}},{"name":"raw","type":{"kind":"simple","type":"slice","optional":false}}]},{"name":"SendParameters","header":null,"fields":[{"name":"bounce","type":{"kind":"simple","type":"bool","optional":false}},{"name":"to","type":{"kind":"simple","type":"address","optional":false}},{"name":"value","type":{"kind":"simple","type":"int","optional":false,"format":257}},{"name":"mode","type":{"kind":"simple","type":"int","optional":false,"format":257}},{"name":"body","type":{"kind":"simple","type":"cell","optional":true}},{"name":"code","type":{"kind":"simple","type":"cell","optional":true}},{"name":"data","type":{"kind":"simple","type":"cell","optional":true}}]},{"name":"Deploy","header":2490013878,"fields":[{"name":"queryId","type":{"kind":"simple","type":"uint","optional":false,"format":64}}]},{"name":"DeployOk","header":2952335191,"fields":[{"name":"queryId","type":{"kind":"simple","type":"uint","optional":false,"format":64}}]},{"name":"FactoryDeploy","header":1829761339,"fields":[{"name":"queryId","type":{"kind":"simple","type":"uint","optional":false,"format":64}},{"name":"cashback","type":{"kind":"simple","type":"address","optional":false}}]}],"receivers":[{"receiver":"internal","message":{"kind":"text","text":"increment"}},{"receiver":"internal","message":{"kind":"typed","type":"Deploy"}}],"getters":[{"name":"getCounter","arguments":[],"returnType":{"kind":"simple","type":"int","optional":false,"format":257}}],"errors":{"2":{"message":"Stack undeflow"},"3":{"message":"Stack overflow"},"4":{"message":"Integer overflow"},"5":{"message":"Integer out of expected range"},"6":{"message":"Invalid opcode"},"7":{"message":"Type check error"},"8":{"message":"Cell overflow"},"9":{"message":"Cell underflow"},"10":{"message":"Dictionary error"},"13":{"message":"Out of gas error"},"32":{"message":"Method ID not found"},"34":{"message":"Action is invalid or not supported"},"37":{"message":"Not enough TON"},"38":{"message":"Not enough extra-currencies"},"128":{"message":"Null reference exception"},"129":{"message":"Invalid serialization prefix"},"130":{"message":"Invalid incoming message"},"131":{"message":"Constraints error"},"132":{"message":"Access denied"},"133":{"message":"Contract stopped"},"134":{"message":"Invalid argument"},"135":{"message":"Code of a contract was not found"},"136":{"message":"Invalid address"},"137":{"message":"Masterchain support is not enabled for this contract"}},"interfaces":["org.ton.introspection.v0","org.ton.abi.ipfs.v0","org.ton.deploy.lazy.v0","org.ton.debug.v0","org.ton.chain.workchain.v0"]} |
Binary file not shown.
127 changes: 127 additions & 0 deletions
127
src/test/features/output/implicit-init_MyContract.code.fc
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 |
---|---|---|
@@ -0,0 +1,127 @@ | ||
#pragma version =0.4.3; | ||
#pragma allow-post-modification; | ||
#pragma compute-asm-ltr; | ||
|
||
#include "implicit-init_MyContract.headers.fc"; | ||
#include "implicit-init_MyContract.stdlib.fc"; | ||
#include "implicit-init_MyContract.storage.fc"; | ||
|
||
;; | ||
;; Contract MyContract functions | ||
;; | ||
|
||
(int) $MyContract$_contract_init() impure inline_ref { | ||
var (($self'counter)) = (0); | ||
return ($self'counter); | ||
} | ||
|
||
((int), int) $MyContract$_fun_getCounter((int) $self) impure inline_ref { | ||
var (($self'counter)) = $self; | ||
return (($self'counter), $self'counter); | ||
} | ||
|
||
;; | ||
;; Receivers of a Contract MyContract | ||
;; | ||
|
||
((int), ()) $MyContract$_internal_text_c4f8d72312edfdef5b7bec7833bdbb162d1511bd78a912aed0f2637af65572ae((int) $self) impure inline { | ||
var ($self'counter) = $self; | ||
$self'counter = $self'counter + 1; | ||
return (($self'counter), ()); | ||
} | ||
|
||
(((int)), ()) $MyContract$_internal_binary_Deploy((int) $self, (int) $deploy) impure inline { | ||
var ($self'counter) = $self; | ||
var ($deploy'queryId) = $deploy; | ||
($self'counter)~$MyContract$_fun_notify($DeployOk$_store_cell($DeployOk$_constructor_queryId($deploy'queryId))); | ||
return (($self'counter), ()); | ||
} | ||
|
||
;; | ||
;; Get methods of a Contract MyContract | ||
;; | ||
|
||
_ %getCounter() method_id(103307) { | ||
var self = $MyContract$_contract_load(); | ||
var res = self~$MyContract$_fun_getCounter(); | ||
return res; | ||
} | ||
|
||
_ supported_interfaces() method_id { | ||
return ( | ||
"org.ton.introspection.v0"H >> 128, | ||
"org.ton.abi.ipfs.v0"H >> 128, | ||
"org.ton.deploy.lazy.v0"H >> 128, | ||
"org.ton.debug.v0"H >> 128, | ||
"org.ton.chain.workchain.v0"H >> 128 | ||
); | ||
} | ||
|
||
_ get_abi_ipfs() method_id { | ||
return "ipfs://QmUMNpuudc6g5LXLYu1TqFHXUkx7rQtuUPpLjexwCKH6R9"; | ||
} | ||
|
||
_ lazy_deployment_completed() method_id { | ||
return get_data().begin_parse().load_int(1); | ||
} | ||
|
||
;; | ||
;; Routing of a Contract MyContract | ||
;; | ||
|
||
((int), int) $MyContract$_contract_router_internal((int) self, int msg_bounced, slice in_msg) impure inline_ref { | ||
;; Handle bounced messages | ||
if (msg_bounced) { | ||
return (self, true); | ||
} | ||
|
||
;; Parse incoming message | ||
int op = 0; | ||
if (slice_bits(in_msg) >= 32) { | ||
op = in_msg.preload_uint(32); | ||
} | ||
|
||
|
||
;; Receive Deploy message | ||
if (op == 2490013878) { | ||
var msg = in_msg~$Deploy$_load(); | ||
self~$MyContract$_internal_binary_Deploy(msg); | ||
return (self, true); | ||
} | ||
|
||
;; Text Receivers | ||
if (op == 0) { | ||
var text_op = slice_hash(in_msg); | ||
|
||
;; Receive "increment" message | ||
if (text_op == 0xc4f8d72312edfdef5b7bec7833bdbb162d1511bd78a912aed0f2637af65572ae) { | ||
self~$MyContract$_internal_text_c4f8d72312edfdef5b7bec7833bdbb162d1511bd78a912aed0f2637af65572ae(); | ||
return (self, true); | ||
} | ||
} | ||
|
||
return (self, false); | ||
} | ||
|
||
() recv_internal(int msg_value, cell in_msg_cell, slice in_msg) impure { | ||
|
||
;; Context | ||
var cs = in_msg_cell.begin_parse(); | ||
var msg_flags = cs~load_uint(4); | ||
var msg_bounced = -(msg_flags & 1); | ||
slice msg_sender_addr = __tact_verify_address(cs~load_msg_addr()); | ||
__tact_context = (msg_bounced, msg_sender_addr, msg_value, cs); | ||
__tact_context_sender = msg_sender_addr; | ||
|
||
;; Load contract data | ||
var self = $MyContract$_contract_load(); | ||
|
||
;; Handle operation | ||
int handled = self~$MyContract$_contract_router_internal(msg_bounced, in_msg); | ||
|
||
;; Throw if not handled | ||
throw_unless(130, handled); | ||
|
||
;; Persist state | ||
$MyContract$_contract_store(self); | ||
} |
Oops, something went wrong.