@effectstream/db 0.100.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/assets-config.json +28 -0
  2. package/migrations/assets.ts +35 -0
  3. package/migrations/readme.md +37 -0
  4. package/migrations/system-down-v-0.0.0.sql +2 -0
  5. package/migrations/system-down-v-0.0.1.sql +14 -0
  6. package/migrations/system-up-v-0.0.0.sql +40 -0
  7. package/migrations/system-up-v-0.0.1.sql +117 -0
  8. package/migrations/system-up-v-0.0.2.sql +22 -0
  9. package/migrations/system-up-v-0.8.1.sql +5 -0
  10. package/migrations/system-version.ts +147 -0
  11. package/package.json +33 -0
  12. package/pgtypedconfig.json +21 -0
  13. package/scripts/Dockerfile +13 -0
  14. package/scripts/apply-migrations.ts +49 -0
  15. package/scripts/pgtyped-internal.ts +43 -0
  16. package/scripts/pgtyped-update.ts +119 -0
  17. package/scripts/start-pglite.ts +71 -0
  18. package/scripts/wait-for-db.ts +43 -0
  19. package/src/dynamic-tables.ts +110 -0
  20. package/src/event-indexing.ts +31 -0
  21. package/src/migrations.ts +28 -0
  22. package/src/mod.ts +65 -0
  23. package/src/pg-connection.test.ts +99 -0
  24. package/src/pg-connection.ts +211 -0
  25. package/src/register-events.ts +40 -0
  26. package/src/scheduled-constructors.ts +117 -0
  27. package/src/snapshot-handler.ts +164 -0
  28. package/src/sql/accounts.queries.ts +350 -0
  29. package/src/sql/accounts.sql +77 -0
  30. package/src/sql/achievements.queries.ts +74 -0
  31. package/src/sql/achievements.sql +17 -0
  32. package/src/sql/block-heights.queries.ts +205 -0
  33. package/src/sql/block-heights.sql +45 -0
  34. package/src/sql/events.queries.ts +201 -0
  35. package/src/sql/events.sql +41 -0
  36. package/src/sql/nonces.queries.ts +85 -0
  37. package/src/sql/nonces.sql +11 -0
  38. package/src/sql/primitives.queries.ts +35 -0
  39. package/src/sql/primitives.sql +4 -0
  40. package/src/sql/rollup_inputs.queries.ts +654 -0
  41. package/src/sql/rollup_inputs.sql +227 -0
  42. package/src/sql/statistics.queries.ts +160 -0
  43. package/src/sql/statistics.sql +55 -0
  44. package/src/sql/sync-protocols/page.queries.ts +140 -0
  45. package/src/sql/sync-protocols/page.sql +39 -0
  46. package/src/sql/system.queries.ts +356 -0
  47. package/src/sql/system.sql +75 -0
  48. package/src/sql/tables.queries.ts +89 -0
  49. package/src/sql/tables.sql +17 -0
  50. package/src/system.ts +41 -0
@@ -0,0 +1,28 @@
1
+ {
2
+ "files": [
3
+ {
4
+ "importPath": "./migrations/system-up-v-0.0.0.sql",
5
+ "calledName": "system-up-v-0-0-0"
6
+ },
7
+ {
8
+ "importPath": "./migrations/system-up-v-0.0.1.sql",
9
+ "calledName": "system-up-v-0-0-1"
10
+ },
11
+ {
12
+ "importPath": "./migrations/system-up-v-0.0.2.sql",
13
+ "calledName": "system-up-v-0-0-2"
14
+ },
15
+ {
16
+ "importPath": "./migrations/system-up-v-0.8.1.sql",
17
+ "calledName": "system-up-v-0-8-1"
18
+ },
19
+ {
20
+ "importPath": "./migrations/system-down-v-0.0.0.sql",
21
+ "calledName": "system-down-v-0-0-0"
22
+ },
23
+ {
24
+ "importPath": "./migrations/system-down-v-0.0.1.sql",
25
+ "calledName": "system-down-v-0-0-1"
26
+ }
27
+ ]
28
+ }
@@ -0,0 +1,35 @@
1
+
2
+ function decodeBase64(b64: string): Uint8Array {
3
+ return Uint8Array.from(atob(b64), c => c.charCodeAt(0));
4
+ }
5
+
6
+ const bundledObject = {
7
+ files:{
8
+ "system-up-v-0-0-0":{
9
+ content:decodeBase64("Q1JFQVRFIFNDSEVNQSBJRiBOT1QgRVhJU1RTIGVmZmVjdHN0cmVhbTsKCkNSRUFURSBFWFRFTlNJT04gSUYgTk9UIEVYSVNUUyBwZ19pdm07CgpDUkVBVEUgVEFCTEUgZWZmZWN0c3RyZWFtLmVmZmVjdHN0cmVhbV9leHBlY3RlZF92ZXJzaW9uICgKICBhcHBfdmVyc2lvbl9tYWpvciBJTlRFR0VSIE5PVCBOVUxMLAogIGFwcF92ZXJzaW9uX21pbm9yIElOVEVHRVIgTk9UIE5VTEwsCiAgYXBwX3ZlcnNpb25fcGF0Y2ggSU5URUdFUiBOT1QgTlVMTCwKICBlbmdpbmVfdmVyc2lvbl9tYWpvciBJTlRFR0VSIE5PVCBOVUxMLAogIGVuZ2luZV92ZXJzaW9uX21pbm9yIElOVEVHRVIgTk9UIE5VTEwsCiAgZW5naW5lX3ZlcnNpb25fcGF0Y2ggSU5URUdFUiBOT1QgTlVMTCwKICBibG9ja19oZWlnaHQgSU5URUdFUiBOT1QgTlVMTAopOwoKQ1JFQVRFIFVOSVFVRSBJTkRFWCBlZmZlY3RzdHJlYW1fZXhwZWN0ZWRfdmVyc2lvbl91bmlxdWVfdmVyc2lvbl9ibG9ja19oZWlnaHQgCk9OIGVmZmVjdHN0cmVhbS5lZmZlY3RzdHJlYW1fZXhwZWN0ZWRfdmVyc2lvbiAKKGFwcF92ZXJzaW9uX21ham9yLCBhcHBfdmVyc2lvbl9taW5vciwgYXBwX3ZlcnNpb25fcGF0Y2gsIAplbmdpbmVfdmVyc2lvbl9tYWpvciwgZW5naW5lX3ZlcnNpb25fbWlub3IsIGVuZ2luZV92ZXJzaW9uX3BhdGNoKTsKCkNSRUFURSBUQUJMRSBlZmZlY3RzdHJlYW0uZWZmZWN0c3RyZWFtX3ZlcnNpb25faGlzdG9yeSAoCiAgYXBwX3ZlcnNpb25fbWFqb3IgSU5URUdFUiBOT1QgTlVMTCwKICBhcHBfdmVyc2lvbl9taW5vciBJTlRFR0VSIE5PVCBOVUxMLAogIGFwcF92ZXJzaW9uX3BhdGNoIElOVEVHRVIgTk9UIE5VTEwsCiAgZW5naW5lX3ZlcnNpb25fbWFqb3IgSU5URUdFUiBOT1QgTlVMTCwKICBlbmdpbmVfdmVyc2lvbl9taW5vciBJTlRFR0VSIE5PVCBOVUxMLAogIGVuZ2luZV92ZXJzaW9uX3BhdGNoIElOVEVHRVIgTk9UIE5VTEwsCiAgYmxvY2tfaGVpZ2h0IElOVEVHRVIgTk9UIE5VTEwKKTsKCkNSRUFURSBVTklRVUUgSU5ERVggZWZmZWN0c3RyZWFtX3ZlcnNpb25faGlzdG9yeV91bmlxdWVfdmVyc2lvbl9ibG9ja19oZWlnaHQgCk9OIGVmZmVjdHN0cmVhbS5lZmZlY3RzdHJlYW1fdmVyc2lvbl9oaXN0b3J5IAooYXBwX3ZlcnNpb25fbWFqb3IsIGFwcF92ZXJzaW9uX21pbm9yLCBhcHBfdmVyc2lvbl9wYXRjaCwgCmVuZ2luZV92ZXJzaW9uX21ham9yLCBlbmdpbmVfdmVyc2lvbl9taW5vciwgZW5naW5lX3ZlcnNpb25fcGF0Y2gpOwoKQ1JFQVRFIFRBQkxFIGVmZmVjdHN0cmVhbS5lZmZlY3RzdHJlYW1fbWlncmF0aW9uX2hpc3RvcnkgKAogIG5hbWUgVEVYVCBOT1QgTlVMTCwKICBibG9ja19oZWlnaHQgSU5URUdFUiBOT1QgTlVMTCwKICBpc19zeXN0ZW1fbWlncmF0aW9uIEJPT0xFQU4gTk9UIE5VTEwKKTsKCg=="),
10
+ extension: "sql"
11
+ },
12
+ "system-up-v-0-0-1":{
13
+ content:decodeBase64("Q1JFQVRFIFNDSEVNQSBJRiBOT1QgRVhJU1RTIGVmZmVjdHN0cmVhbTsKQ1JFQVRFIFNDSEVNQSBJRiBOT1QgRVhJU1RTIHByaW1pdGl2ZXM7CgpDUkVBVEUgVEFCTEUgZWZmZWN0c3RyZWFtLmVmZmVjdHN0cmVhbV9ibG9ja3MgKAogIGJsb2NrX2hlaWdodCBJTlRFR0VSIFBSSU1BUlkgS0VZLAogIHZlciBJTlRFR0VSIE5PVCBOVUxMLAogIG1haW5fY2hhaW5fYmxvY2tfaGFzaCBCWVRFQSBOT1QgTlVMTCwKICBzZWVkIFRFWFQgTk9UIE5VTEwsCiAgbXNfdGltZXN0YW1wIFRJTUVTVEFNUCB3aXRob3V0IHRpbWUgem9uZSBOT1QgTlVMTCwKICBlZmZlY3RzdHJlYW1fYmxvY2tfaGFzaCBCWVRFQQopOwoKQ1JFQVRFIFRBQkxFIGVmZmVjdHN0cmVhbS5yb2xsdXBfaW5wdXRzICgKICBpZCBTRVJJQUwgUFJJTUFSWSBLRVksCiAgZnJvbV9hZGRyZXNzIFRFWFQgTk9UIE5VTEwsCiAgZnJvbV9hZGRyZXNzX3R5cGUgSU5URUdFUiBOT1QgTlVMTCwKICBpbnB1dF9kYXRhIFRFWFQgTk9UIE5VTEwKKTsKCkNSRUFURSBUQUJMRSBlZmZlY3RzdHJlYW0ucm9sbHVwX2lucHV0X2Z1dHVyZV9ibG9jayAoCiAgaWQgSU5URUdFUiBQUklNQVJZIEtFWSBSRUZFUkVOQ0VTIGVmZmVjdHN0cmVhbS5yb2xsdXBfaW5wdXRzKGlkKSBPTiBERUxFVEUgQ0FTQ0FERSwKICBmdXR1cmVfYmxvY2tfaGVpZ2h0IElOVEVHRVIgTk9UIE5VTEwKKTsKQ1JFQVRFIFRBQkxFIGVmZmVjdHN0cmVhbS5yb2xsdXBfaW5wdXRfZnV0dXJlX3RpbWVzdGFtcCAoCiAgaWQgSU5URUdFUiBQUklNQVJZIEtFWSBSRUZFUkVOQ0VTIGVmZmVjdHN0cmVhbS5yb2xsdXBfaW5wdXRzKGlkKSBPTiBERUxFVEUgQ0FTQ0FERSwKICBmdXR1cmVfbXNfdGltZXN0YW1wIFRJTUVTVEFNUCB3aXRob3V0IHRpbWUgem9uZSBOT1QgTlVMTAopOwoKQ1JFQVRFIFRBQkxFIGVmZmVjdHN0cmVhbS5yb2xsdXBfaW5wdXRfcmVzdWx0ICgKICBpZCBJTlRFR0VSIFBSSU1BUlkgS0VZIFJFRkVSRU5DRVMgZWZmZWN0c3RyZWFtLnJvbGx1cF9pbnB1dHMoaWQpIE9OIERFTEVURSBDQVNDQURFLAogIHN1Y2Nlc3MgQk9PTEVBTiBOT1QgTlVMTCwKICBlZmZlY3RzdHJlYW1fdHhfaGFzaCBCWVRFQSBOT1QgTlVMTCwKICBibG9ja19oZWlnaHQgSU5URUdFUiBOT1QgTlVMTCBSRUZFUkVOQ0VTIGVmZmVjdHN0cmVhbS5lZmZlY3RzdHJlYW1fYmxvY2tzKGJsb2NrX2hlaWdodCksCiAgaW5kZXhfaW5fYmxvY2sgSU5URUdFUiBOT1QgTlVMTAopOwoKQ1JFQVRFIFRBQkxFIGVmZmVjdHN0cmVhbS5yb2xsdXBfaW5wdXRfb3JpZ2luICgKICBpZCBJTlRFR0VSIFBSSU1BUlkgS0VZIFJFRkVSRU5DRVMgZWZmZWN0c3RyZWFtLnJvbGx1cF9pbnB1dHMoaWQpIE9OIERFTEVURSBDQVNDQURFLAogIHByaW1pdGl2ZV9uYW1lIFRFWFQsCiAgY2FpcDIgVEVYVCwKICB0eF9oYXNoIEJZVEVBLAogIGNvbnRyYWN0X2FkZHJlc3MgVEVYVAopOwoKQ1JFQVRFIFRBQkxFIGVmZmVjdHN0cmVhbS5wcmltaXRpdmVfYWNjb3VudGluZyAoCiAgcHJpbWl0aXZlX25hbWUgVEVYVCBOT1QgTlVMTCwKICBpZCBTRVJJQUwsCiAgZWZmZWN0c3RyZWFtX2Jsb2NrX2hlaWdodCBJTlRFR0VSIE5PVCBOVUxMIFJFRkVSRU5DRVMgZWZmZWN0c3RyZWFtLmVmZmVjdHN0cmVhbV9ibG9ja3MoYmxvY2tfaGVpZ2h0KSwKICBwYXlsb2FkX3R5cGUgVEVYVCBOT1QgTlVMTCwKICBwYXlsb2FkIEpTT04gTk9UIE5VTEwsCiAgcGF5bG9hZF9oYXNoIFRFWFQgR0VORVJBVEVEIEFMV0FZUyBBUyAobWQ1KHBheWxvYWQ6OnRleHQpKSBTVE9SRUQsCiAgUFJJTUFSWSBLRVkgKHByaW1pdGl2ZV9uYW1lLCBpZCkKKTsKCkNSRUFURSBUQUJMRSBlZmZlY3RzdHJlYW0ubm9uY2VzICgKICBub25jZSBURVhUIFBSSU1BUlkgS0VZLAogIGJsb2NrX2hlaWdodCBJTlRFR0VSIE5PVCBOVUxMIFJFRkVSRU5DRVMgZWZmZWN0c3RyZWFtLmVmZmVjdHN0cmVhbV9ibG9ja3MoYmxvY2tfaGVpZ2h0KQopOwoKQ1JFQVRFIFRBQkxFIGVmZmVjdHN0cmVhbS5zeW5jX3Byb3RvY29sX3BhZ2luYXRpb24gKAogIHByb3RvY29sX25hbWUgVEVYVCBOT1QgTlVMTCwKICBwYWdlX251bWJlciBJTlRFR0VSIE5PVCBOVUxMLAogIHBhZ2UgSlNPTkIgTk9UIE5VTEwsCiAgUFJJTUFSWSBLRVkgKHByb3RvY29sX25hbWUsIHBhZ2VfbnVtYmVyKQopOwoKQ1JFQVRFIElOREVYIHN5bmNfcHJvdG9jb2xfcGFnaW5hdGlvbl9wYWdlX251bWJlcl9pZHggb24gZWZmZWN0c3RyZWFtLnN5bmNfcHJvdG9jb2xfcGFnaW5hdGlvbihwcm90b2NvbF9uYW1lLCBwYWdlX251bWJlcik7CgpDUkVBVEUgVEFCTEUgZWZmZWN0c3RyZWFtLnByaW1pdGl2ZV9jb25maWcgKAogIHByaW1pdGl2ZV9uYW1lIFRFWFQgUFJJTUFSWSBLRVksCiAgcHJpbWl0aXZlX3R5cGUgVEVYVCBOT1QgTlVMTCwKICBwcmltaXRpdmVfY2FpcDIgVEVYVCBOT1QgTlVMTCwKICBwcm90b2NvbF9uYW1lIFRFWFQgTk9UIE5VTEwsCiAgY29uZmlnIEpTT05CIE5PVCBOVUxMLAogIGNvbmZpZ19oYXNoIElOVEVHRVIgTk9UIE5VTEwsCiAgcGFyZW50X25hbWUgVEVYVAopOwoKQ1JFQVRFIFRBQkxFIGVmZmVjdHN0cmVhbS5hY2NvdW50cyAoCiAgaWQgU0VSSUFMIFBSSU1BUlkgS0VZLAogIHByaW1hcnlfYWRkcmVzcyBURVhUCik7CgpDUkVBVEUgVEFCTEUgZWZmZWN0c3RyZWFtLmFkZHJlc3NlcyAoCiAgYWRkcmVzcyBURVhUIE5PVCBOVUxMIFVOSVFVRSwKICBhZGRyZXNzX3R5cGUgSU5URUdFUiBOT1QgTlVMTCwKICBhY2NvdW50X2lkIElOVEVHRVIgUkVGRVJFTkNFUyBlZmZlY3RzdHJlYW0uYWNjb3VudHMoaWQpCik7CgpDUkVBVEUgSU5ERVggYWRkcmVzc2VzX2FjY291bnRfaWRfaWR4IE9OIGVmZmVjdHN0cmVhbS5hZGRyZXNzZXMoYWNjb3VudF9pZCk7CgpBTFRFUiBUQUJMRSBlZmZlY3RzdHJlYW0uYWNjb3VudHMgQUREIENPTlNUUkFJTlQgZmtfcHJpbWFyeV9hZGRyZXNzX2FkZHJlc3MgRk9SRUlHTiBLRVkgKHByaW1hcnlfYWRkcmVzcykgUkVGRVJFTkNFUyBlZmZlY3RzdHJlYW0uYWRkcmVzc2VzKGFkZHJlc3MpOwoKQ1JFQVRFIFRBQkxFIGVmZmVjdHN0cmVhbS5hY2hpZXZlbWVudF9wcm9ncmVzcygKICBhY2NvdW50X2lkIElOVEVHRVIgTk9UIE5VTEwgUkVGRVJFTkNFUyBlZmZlY3RzdHJlYW0uYWNjb3VudHMoaWQpLAogIG5hbWUgVEVYVCBOT1QgTlVMTCwKICBjb21wbGV0ZWRfZGF0ZSBUSU1FU1RBTVAsCiAgcHJvZ3Jlc3MgSU5URUdFUiwKICB0b3RhbCBJTlRFR0VSLAogIFBSSU1BUlkgS0VZIChhY2NvdW50X2lkLCBuYW1lKQopOwoKQ1JFQVRFIFRBQkxFIGVmZmVjdHN0cmVhbS5ldmVudCAoCiAgaWQgU0VSSUFMIFBSSU1BUlkgS0VZLAogIHRvcGljIFRFWFQgTk9UIE5VTEwsCiAgYWRkcmVzcyBURVhUIE5PVCBOVUxMLAogIGRhdGEgSlNPTkIgTk9UIE5VTEwsCiAgYmxvY2tfaGVpZ2h0IElOVEVHRVIgTk9UIE5VTEwsCiAgdHhfaW5kZXggSU5URUdFUiBOT1QgTlVMTCwKICBsb2dfaW5kZXggSU5URUdFUiBOT1QgTlVMTAopOwoKQ1JFQVRFIFRBQkxFIGVmZmVjdHN0cmVhbS5yZWdpc3RlcmVkX2V2ZW50ICgKICBuYW1lIFRFWFQgTk9UIE5VTEwsCiAgdG9waWMgVEVYVCBOT1QgTlVMTCwKICBQUklNQVJZIEtFWShuYW1lLCB0b3BpYykKKTsK"),
14
+ extension: "sql"
15
+ },
16
+ "system-up-v-0-0-2":{
17
+ content:decodeBase64("LS0gRW5mb3JjZSB1bmlxdWVuZXNzIGZvciBtaWdyYXRpb24gaGlzdG9yeSBlbnRyaWVzCkNSRUFURSBVTklRVUUgSU5ERVggSUYgTk9UIEVYSVNUUyBlZmZlY3RzdHJlYW1fbWlncmF0aW9uX2hpc3RvcnlfdW5pcXVlX25hbWVfc3lzdGVtCk9OIGVmZmVjdHN0cmVhbS5lZmZlY3RzdHJlYW1fbWlncmF0aW9uX2hpc3RvcnkgKG5hbWUsIGlzX3N5c3RlbV9taWdyYXRpb24pOwoKLS0gQWRkIGlkZW1wb3RlbmN5IHN1cHBvcnQgZm9yIHByaW1pdGl2ZSBhY2NvdW50aW5nIGVudHJpZXMKRE8gJCQKQkVHSU4KICBJRiBOT1QgRVhJU1RTICgKICAgIFNFTEVDVCAxCiAgICBGUk9NIGluZm9ybWF0aW9uX3NjaGVtYS5jb2x1bW5zCiAgICBXSEVSRSB0YWJsZV9zY2hlbWEgPSAnZWZmZWN0c3RyZWFtJwogICAgICBBTkQgdGFibGVfbmFtZSA9ICdwcmltaXRpdmVfYWNjb3VudGluZycKICAgICAgQU5EIGNvbHVtbl9uYW1lID0gJ3BheWxvYWRfaGFzaCcKICApIFRIRU4KICAgIEFMVEVSIFRBQkxFIGVmZmVjdHN0cmVhbS5wcmltaXRpdmVfYWNjb3VudGluZwogICAgICBBREQgQ09MVU1OIHBheWxvYWRfaGFzaCBURVhUIEdFTkVSQVRFRCBBTFdBWVMgQVMgKG1kNShwYXlsb2FkOjp0ZXh0KSkgU1RPUkVEOwogIEVORCBJRjsKRU5ECiQkOwoKQ1JFQVRFIFVOSVFVRSBJTkRFWCBJRiBOT1QgRVhJU1RTIHByaW1pdGl2ZV9hY2NvdW50aW5nX3VuaXF1ZV9wYXlsb2FkX3Blcl9ibG9jawpPTiBlZmZlY3RzdHJlYW0ucHJpbWl0aXZlX2FjY291bnRpbmcgKHByaW1pdGl2ZV9uYW1lLCBlZmZlY3RzdHJlYW1fYmxvY2tfaGVpZ2h0LCBwYXlsb2FkX2hhc2gpOwo="),
18
+ extension: "sql"
19
+ },
20
+ "system-up-v-0-8-1":{
21
+ content:decodeBase64("Q1JFQVRFIFRBQkxFIGVmZmVjdHN0cmVhbS5zeW5jX3Byb3RvY29sX2NvbmZpZ19zbmFwc2hvdCAoCiAgcHJvdG9jb2xfbmFtZSBURVhUIFBSSU1BUlkgS0VZLAogIG5ldHdvcmtfdHlwZSBURVhUIE5PVCBOVUxMLAogIGltbXV0YWJsZV9jb25maWcgSlNPTkIgTk9UIE5VTEwKKTsK"),
22
+ extension: "sql"
23
+ },
24
+ "system-down-v-0-0-0":{
25
+ content:decodeBase64("RFJPUCBUQUJMRSBlZmZlY3RzdHJlYW0uZWZmZWN0c3RyZWFtX3ZlcnNpb25faGlzdG9yeTsKRFJPUCBUQUJMRSBlZmZlY3RzdHJlYW0uZWZmZWN0c3RyZWFtX21pZ3JhdGlvbl9oaXN0b3J5Ow=="),
26
+ extension: "sql"
27
+ },
28
+ "system-down-v-0-0-1":{
29
+ content:decodeBase64("RFJPUCBUQUJMRSBlZmZlY3RzdHJlYW0uZWZmZWN0c3RyZWFtX2Jsb2NrczsKRFJPUCBUQUJMRSBlZmZlY3RzdHJlYW0ucm9sbHVwX2lucHV0czsKRFJPUCBUQUJMRSBlZmZlY3RzdHJlYW0ucm9sbHVwX2lucHV0X2Z1dHVyZV9ibG9jazsKRFJPUCBUQUJMRSBlZmZlY3RzdHJlYW0ucm9sbHVwX2lucHV0X2Z1dHVyZV90aW1lc3RhbXA7CkRST1AgVEFCTEUgZWZmZWN0c3RyZWFtLnJvbGx1cF9pbnB1dF9yZXN1bHQ7CkRST1AgVEFCTEUgZWZmZWN0c3RyZWFtLnJvbGx1cF9pbnB1dF9vcmlnaW47CkRST1AgVEFCTEUgZWZmZWN0c3RyZWFtLm5vbmNlczsKRFJPUCBUQUJMRSBlZmZlY3RzdHJlYW0uc3luY19wcm90b2NvbF9wYWdpbmF0aW9uOwpEUk9QIFRBQkxFIGVmZmVjdHN0cmVhbS5wcmltaXRpdmVfY29uZmlnOwpEUk9QIFRBQkxFIGVmZmVjdHN0cmVhbS5hZGRyZXNzZXM7CkRST1AgVEFCTEUgZWZmZWN0c3RyZWFtLmRlbGVnYXRpb25zOwpEUk9QIFRBQkxFIGVmZmVjdHN0cmVhbS5hY2hpZXZlbWVudF9wcm9ncmVzczsKRFJPUCBUQUJMRSBlZmZlY3RzdHJlYW0uZXZlbnQ7CkRST1AgVEFCTEUgZWZmZWN0c3RyZWFtLnJlZ2lzdGVyZWRfZXZlbnQ7Cg=="),
30
+ extension: "sql"
31
+ }
32
+ }
33
+ }
34
+ export default bundledObject;
35
+
@@ -0,0 +1,37 @@
1
+ # Effectstream DB Management
2
+
3
+ `System Migrations` create and update the DB structure to run with specific
4
+ versions of Effectstream.\
5
+ All migrations are applied that are <= than the current version.
6
+
7
+ > Note v0.0.0 is a special migration that gets applied once before the chain
8
+ > sync
9
+
10
+ ### Migration Files
11
+
12
+ Files must be named as the version where they will be applied.\
13
+ E.g.,
14
+
15
+ - system-up-v-0.3.20
16
+ - system-up-v-1.0.0
17
+
18
+ ### Version
19
+
20
+ Package Version is the System Version.\
21
+ Version in root `deno.json` must be kept in sync with `system-version.ts`, as we
22
+ cannot read this file from the executing engine.
23
+
24
+ ### Deno JSR
25
+
26
+ At the time JSR requires to bundle assets in TS. This is automatically applied
27
+ when the Pgtyped is called
28
+
29
+ ```
30
+ deno task pgtyped:update
31
+ ```
32
+
33
+ generate assets.ts from packages/node-sdk/db directory
34
+
35
+ ```
36
+ rm ./migrations/assets.ts && deno run --allow-read jsr:@codemonument/asset-builder --import-file assets-config.json >> ./migrations/assets.ts
37
+ ```
@@ -0,0 +1,2 @@
1
+ DROP TABLE effectstream.effectstream_version_history;
2
+ DROP TABLE effectstream.effectstream_migration_history;
@@ -0,0 +1,14 @@
1
+ DROP TABLE effectstream.effectstream_blocks;
2
+ DROP TABLE effectstream.rollup_inputs;
3
+ DROP TABLE effectstream.rollup_input_future_block;
4
+ DROP TABLE effectstream.rollup_input_future_timestamp;
5
+ DROP TABLE effectstream.rollup_input_result;
6
+ DROP TABLE effectstream.rollup_input_origin;
7
+ DROP TABLE effectstream.nonces;
8
+ DROP TABLE effectstream.sync_protocol_pagination;
9
+ DROP TABLE effectstream.primitive_config;
10
+ DROP TABLE effectstream.addresses;
11
+ DROP TABLE effectstream.delegations;
12
+ DROP TABLE effectstream.achievement_progress;
13
+ DROP TABLE effectstream.event;
14
+ DROP TABLE effectstream.registered_event;
@@ -0,0 +1,40 @@
1
+ CREATE SCHEMA IF NOT EXISTS effectstream;
2
+
3
+ CREATE EXTENSION IF NOT EXISTS pg_ivm;
4
+
5
+ CREATE TABLE effectstream.effectstream_expected_version (
6
+ app_version_major INTEGER NOT NULL,
7
+ app_version_minor INTEGER NOT NULL,
8
+ app_version_patch INTEGER NOT NULL,
9
+ engine_version_major INTEGER NOT NULL,
10
+ engine_version_minor INTEGER NOT NULL,
11
+ engine_version_patch INTEGER NOT NULL,
12
+ block_height INTEGER NOT NULL
13
+ );
14
+
15
+ CREATE UNIQUE INDEX effectstream_expected_version_unique_version_block_height
16
+ ON effectstream.effectstream_expected_version
17
+ (app_version_major, app_version_minor, app_version_patch,
18
+ engine_version_major, engine_version_minor, engine_version_patch);
19
+
20
+ CREATE TABLE effectstream.effectstream_version_history (
21
+ app_version_major INTEGER NOT NULL,
22
+ app_version_minor INTEGER NOT NULL,
23
+ app_version_patch INTEGER NOT NULL,
24
+ engine_version_major INTEGER NOT NULL,
25
+ engine_version_minor INTEGER NOT NULL,
26
+ engine_version_patch INTEGER NOT NULL,
27
+ block_height INTEGER NOT NULL
28
+ );
29
+
30
+ CREATE UNIQUE INDEX effectstream_version_history_unique_version_block_height
31
+ ON effectstream.effectstream_version_history
32
+ (app_version_major, app_version_minor, app_version_patch,
33
+ engine_version_major, engine_version_minor, engine_version_patch);
34
+
35
+ CREATE TABLE effectstream.effectstream_migration_history (
36
+ name TEXT NOT NULL,
37
+ block_height INTEGER NOT NULL,
38
+ is_system_migration BOOLEAN NOT NULL
39
+ );
40
+
@@ -0,0 +1,117 @@
1
+ CREATE SCHEMA IF NOT EXISTS effectstream;
2
+ CREATE SCHEMA IF NOT EXISTS primitives;
3
+
4
+ CREATE TABLE effectstream.effectstream_blocks (
5
+ block_height INTEGER PRIMARY KEY,
6
+ ver INTEGER NOT NULL,
7
+ main_chain_block_hash BYTEA NOT NULL,
8
+ seed TEXT NOT NULL,
9
+ ms_timestamp TIMESTAMP without time zone NOT NULL,
10
+ effectstream_block_hash BYTEA
11
+ );
12
+
13
+ CREATE TABLE effectstream.rollup_inputs (
14
+ id SERIAL PRIMARY KEY,
15
+ from_address TEXT NOT NULL,
16
+ from_address_type INTEGER NOT NULL,
17
+ input_data TEXT NOT NULL
18
+ );
19
+
20
+ CREATE TABLE effectstream.rollup_input_future_block (
21
+ id INTEGER PRIMARY KEY REFERENCES effectstream.rollup_inputs(id) ON DELETE CASCADE,
22
+ future_block_height INTEGER NOT NULL
23
+ );
24
+ CREATE TABLE effectstream.rollup_input_future_timestamp (
25
+ id INTEGER PRIMARY KEY REFERENCES effectstream.rollup_inputs(id) ON DELETE CASCADE,
26
+ future_ms_timestamp TIMESTAMP without time zone NOT NULL
27
+ );
28
+
29
+ CREATE TABLE effectstream.rollup_input_result (
30
+ id INTEGER PRIMARY KEY REFERENCES effectstream.rollup_inputs(id) ON DELETE CASCADE,
31
+ success BOOLEAN NOT NULL,
32
+ effectstream_tx_hash BYTEA NOT NULL,
33
+ block_height INTEGER NOT NULL REFERENCES effectstream.effectstream_blocks(block_height),
34
+ index_in_block INTEGER NOT NULL
35
+ );
36
+
37
+ CREATE TABLE effectstream.rollup_input_origin (
38
+ id INTEGER PRIMARY KEY REFERENCES effectstream.rollup_inputs(id) ON DELETE CASCADE,
39
+ primitive_name TEXT,
40
+ caip2 TEXT,
41
+ tx_hash BYTEA,
42
+ contract_address TEXT
43
+ );
44
+
45
+ CREATE TABLE effectstream.primitive_accounting (
46
+ primitive_name TEXT NOT NULL,
47
+ id SERIAL,
48
+ effectstream_block_height INTEGER NOT NULL REFERENCES effectstream.effectstream_blocks(block_height),
49
+ payload_type TEXT NOT NULL,
50
+ payload JSON NOT NULL,
51
+ payload_hash TEXT GENERATED ALWAYS AS (md5(payload::text)) STORED,
52
+ PRIMARY KEY (primitive_name, id)
53
+ );
54
+
55
+ CREATE TABLE effectstream.nonces (
56
+ nonce TEXT PRIMARY KEY,
57
+ block_height INTEGER NOT NULL REFERENCES effectstream.effectstream_blocks(block_height)
58
+ );
59
+
60
+ CREATE TABLE effectstream.sync_protocol_pagination (
61
+ protocol_name TEXT NOT NULL,
62
+ page_number INTEGER NOT NULL,
63
+ page JSONB NOT NULL,
64
+ PRIMARY KEY (protocol_name, page_number)
65
+ );
66
+
67
+ CREATE INDEX sync_protocol_pagination_page_number_idx on effectstream.sync_protocol_pagination(protocol_name, page_number);
68
+
69
+ CREATE TABLE effectstream.primitive_config (
70
+ primitive_name TEXT PRIMARY KEY,
71
+ primitive_type TEXT NOT NULL,
72
+ primitive_caip2 TEXT NOT NULL,
73
+ protocol_name TEXT NOT NULL,
74
+ config JSONB NOT NULL,
75
+ config_hash INTEGER NOT NULL,
76
+ parent_name TEXT
77
+ );
78
+
79
+ CREATE TABLE effectstream.accounts (
80
+ id SERIAL PRIMARY KEY,
81
+ primary_address TEXT
82
+ );
83
+
84
+ CREATE TABLE effectstream.addresses (
85
+ address TEXT NOT NULL UNIQUE,
86
+ address_type INTEGER NOT NULL,
87
+ account_id INTEGER REFERENCES effectstream.accounts(id)
88
+ );
89
+
90
+ CREATE INDEX addresses_account_id_idx ON effectstream.addresses(account_id);
91
+
92
+ ALTER TABLE effectstream.accounts ADD CONSTRAINT fk_primary_address_address FOREIGN KEY (primary_address) REFERENCES effectstream.addresses(address);
93
+
94
+ CREATE TABLE effectstream.achievement_progress(
95
+ account_id INTEGER NOT NULL REFERENCES effectstream.accounts(id),
96
+ name TEXT NOT NULL,
97
+ completed_date TIMESTAMP,
98
+ progress INTEGER,
99
+ total INTEGER,
100
+ PRIMARY KEY (account_id, name)
101
+ );
102
+
103
+ CREATE TABLE effectstream.event (
104
+ id SERIAL PRIMARY KEY,
105
+ topic TEXT NOT NULL,
106
+ address TEXT NOT NULL,
107
+ data JSONB NOT NULL,
108
+ block_height INTEGER NOT NULL,
109
+ tx_index INTEGER NOT NULL,
110
+ log_index INTEGER NOT NULL
111
+ );
112
+
113
+ CREATE TABLE effectstream.registered_event (
114
+ name TEXT NOT NULL,
115
+ topic TEXT NOT NULL,
116
+ PRIMARY KEY(name, topic)
117
+ );
@@ -0,0 +1,22 @@
1
+ -- Enforce uniqueness for migration history entries
2
+ CREATE UNIQUE INDEX IF NOT EXISTS effectstream_migration_history_unique_name_system
3
+ ON effectstream.effectstream_migration_history (name, is_system_migration);
4
+
5
+ -- Add idempotency support for primitive accounting entries
6
+ DO $$
7
+ BEGIN
8
+ IF NOT EXISTS (
9
+ SELECT 1
10
+ FROM information_schema.columns
11
+ WHERE table_schema = 'effectstream'
12
+ AND table_name = 'primitive_accounting'
13
+ AND column_name = 'payload_hash'
14
+ ) THEN
15
+ ALTER TABLE effectstream.primitive_accounting
16
+ ADD COLUMN payload_hash TEXT GENERATED ALWAYS AS (md5(payload::text)) STORED;
17
+ END IF;
18
+ END
19
+ $$;
20
+
21
+ CREATE UNIQUE INDEX IF NOT EXISTS primitive_accounting_unique_payload_per_block
22
+ ON effectstream.primitive_accounting (primitive_name, effectstream_block_height, payload_hash);
@@ -0,0 +1,5 @@
1
+ CREATE TABLE effectstream.sync_protocol_config_snapshot (
2
+ protocol_name TEXT PRIMARY KEY,
3
+ network_type TEXT NOT NULL,
4
+ immutable_config JSONB NOT NULL
5
+ );
@@ -0,0 +1,147 @@
1
+ import type { Client } from "pg";
2
+ import type { Operation } from "effection";
3
+ import { until } from "effection";
4
+ import * as migrationFiles from "./assets.ts";
5
+ import {
6
+ acquireDBMutex,
7
+ getLatestProcessedBlockHeight,
8
+ getLatestVersion,
9
+ releaseDBMutex,
10
+ tableExists,
11
+ } from "@effectstream/db";
12
+ type VERSION = `${number}.${number}.${number}`;
13
+ type VERSION_NUMBER = [number, number, number];
14
+ // NOTE This must match the version of the root deno.json
15
+ export const EFFECTSTREAM_ENGINE_VERSION: VERSION = "0.8.1";
16
+
17
+ export { applyMigrations } from "../scripts/apply-migrations.ts";
18
+
19
+ export function parseVersion(version: VERSION): VERSION_NUMBER {
20
+ const parts = version.split(".").map((part) => Number(part));
21
+ if (parts.length !== 3 || parts.some((n) => Number.isNaN(n))) {
22
+ throw new Error(`Invalid version string: ${version}`);
23
+ }
24
+ const [major, minor, patch] = parts;
25
+ return [major, minor, patch];
26
+ }
27
+
28
+ export async function getMigrations(
29
+ from_version: VERSION | undefined = undefined,
30
+ to_version: VERSION = EFFECTSTREAM_ENGINE_VERSION,
31
+ ): Promise<{
32
+ version: VERSION;
33
+ sql: string;
34
+ }[]> {
35
+ const toVersion: VERSION_NUMBER = parseVersion(to_version);
36
+ const fromVersion: VERSION_NUMBER | undefined = from_version
37
+ ? parseVersion(from_version)
38
+ : undefined;
39
+
40
+ const upMigrations: { version: VERSION_NUMBER; sql: string }[] = [];
41
+ Object.entries(migrationFiles.default.files).map(([key, value]) => {
42
+ const [s, type, v, major, minor, patch] = key.split("-");
43
+ if (s === "system" && type === "up" && v === "v") {
44
+ upMigrations.push({
45
+ version: [
46
+ parseInt(major, 10),
47
+ parseInt(minor, 10),
48
+ parseInt(patch, 10),
49
+ ],
50
+ sql: new TextDecoder().decode(value.content),
51
+ });
52
+ }
53
+ });
54
+
55
+ const filteredAndSorted = upMigrations
56
+ .filter((migration) => {
57
+ return (
58
+ (!fromVersion || (
59
+ // Return all migrations that are greater to the from version
60
+ migration.version[0] > fromVersion[0] ||
61
+ (migration.version[0] === fromVersion[0] &&
62
+ migration.version[1] > fromVersion[1]) ||
63
+ (migration.version[0] === fromVersion[0] &&
64
+ migration.version[1] === fromVersion[1] &&
65
+ migration.version[2] > fromVersion[2])
66
+ )) &&
67
+ // Return all migrations that are less or equal to the target version
68
+ (
69
+ migration.version[0] < toVersion[0] ||
70
+ (migration.version[0] === toVersion[0] &&
71
+ migration.version[1] < toVersion[1]) ||
72
+ (migration.version[0] === toVersion[0] &&
73
+ migration.version[1] === toVersion[1] &&
74
+ migration.version[2] <= toVersion[2])
75
+ )
76
+ );
77
+ })
78
+ .sort((a, b) => {
79
+ // Sort from oldest to newest
80
+ return (
81
+ a.version[0] - b.version[0] ||
82
+ a.version[1] - b.version[1] ||
83
+ a.version[2] - b.version[2]
84
+ );
85
+ });
86
+
87
+ return filteredAndSorted.map((migration) => ({
88
+ version: `${migration.version[0]}.${migration.version[1]}.${
89
+ migration.version[2]
90
+ }`,
91
+ sql: migration.sql,
92
+ }));
93
+ }
94
+
95
+ export type VersionInfo = {
96
+ engine_current_version: VERSION;
97
+ engine_previous_version: VERSION;
98
+ app_previous_version: VERSION;
99
+ is_empty: boolean;
100
+ };
101
+
102
+ export function* getLastBlockHeight(
103
+ versionInfo: VersionInfo,
104
+ dbConn: Client,
105
+ ): Operation<number> {
106
+ yield* acquireDBMutex("get-last-block-height");
107
+ const v = versionInfo.is_empty
108
+ ? 0
109
+ : (yield* until(getLatestProcessedBlockHeight.run(undefined, dbConn)))[0]
110
+ .block_height;
111
+ releaseDBMutex("get-last-block-height");
112
+ return v;
113
+ }
114
+
115
+ export function* getVersionInfo(dbConn: Client): Operation<VersionInfo> {
116
+ // 1. Let's check if the database is empty.
117
+ yield* acquireDBMutex("get-version-info");
118
+ const [result] = yield* until(tableExists.run(undefined, dbConn));
119
+ releaseDBMutex("get-version-info");
120
+
121
+ if (!result.exists) {
122
+ return {
123
+ engine_current_version: EFFECTSTREAM_ENGINE_VERSION,
124
+ engine_previous_version: "0.0.0",
125
+ app_previous_version: "0.0.0",
126
+ is_empty: true,
127
+ };
128
+ }
129
+
130
+ // So let's check what is the latest version from the `effectstream_version_history` table.
131
+ yield* acquireDBMutex("get-version-info");
132
+ const [latestVersion] = yield* until(getLatestVersion.run(undefined, dbConn));
133
+ releaseDBMutex("get-version-info");
134
+
135
+ if (!latestVersion) {
136
+ throw new Error("Internal error: No version found in the database");
137
+ }
138
+
139
+ return {
140
+ engine_current_version: EFFECTSTREAM_ENGINE_VERSION,
141
+ engine_previous_version:
142
+ `${latestVersion.engine_version_major}.${latestVersion.engine_version_minor}.${latestVersion.engine_version_patch}`,
143
+ app_previous_version:
144
+ `${latestVersion.app_version_major}.${latestVersion.app_version_minor}.${latestVersion.app_version_patch}`,
145
+ is_empty: false,
146
+ };
147
+ }
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@effectstream/db",
3
+ "version": "0.100.0",
4
+ "license": "MIT",
5
+ "exports": {
6
+ ".": "./src/mod.ts",
7
+ "./start-pglite": "./scripts/start-pglite.ts",
8
+ "./apply-migrations": "./scripts/apply-migrations.ts",
9
+ "./db-up": "./scripts/start-pglite.ts",
10
+ "./db-wait": "./scripts/wait-for-db.ts",
11
+ "./pgtyped-update": "./scripts/pgtyped-update.ts",
12
+ "./version": "./migrations/system-version.ts"
13
+ },
14
+ "dependencies": {
15
+ "@effectstream/coroutine": "0.100.0",
16
+ "@effectstream/log": "0.100.0",
17
+ "@effectstream/runtime": "0.100.0",
18
+ "@effectstream/sync": "0.100.0",
19
+ "@effectstream/utils": "0.100.0",
20
+ "@electric-sql/pglite": "^0.3.14",
21
+ "@pgtyped/runtime": "2.4.2",
22
+ "@pgtyped/parser": "2.4.2",
23
+ "pg": "8.17.2",
24
+ "pg-tx": "^1.0.1",
25
+ "effection": "^3.5.0",
26
+ "pg-gateway": "^0.3.0-beta.4"
27
+ },
28
+ "devDependencies": {
29
+ "@paima/pgtyped-cli": "^2.4.5",
30
+ "wait-on": "8.0.3",
31
+ "concurrently": "9.1.2"
32
+ }
33
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "transforms": [
3
+ {
4
+ "mode": "sql",
5
+ "include": "**/*.sql",
6
+ "emitTemplate": "{{dir}}/{{name}}.queries.ts"
7
+ }
8
+ ],
9
+ "srcDir": "./src/sql",
10
+ "failOnError": false,
11
+ "camelCaseColumnNames": false,
12
+ "db": {
13
+ "dbName": "postgres",
14
+ "user": "postgres",
15
+ "password": "postgres",
16
+ "host": "localhost",
17
+ "port": 5432,
18
+ "ssl": false
19
+ },
20
+ "maxWorkerThreads": 1
21
+ }
@@ -0,0 +1,13 @@
1
+ FROM postgres:15.9 AS builder
2
+
3
+ RUN apt-get update && apt-get -y install git postgresql-server-dev-15 build-essential && rm -rf /var/lib/apt/lists/*
4
+
5
+ RUN git clone https://github.com/sraoss/pg_ivm
6
+ WORKDIR /pg_ivm
7
+
8
+ RUN git checkout v1.11
9
+ RUN make
10
+ RUN make DESTDIR=/pg_ivm/output install
11
+
12
+ FROM postgres:15.9
13
+ COPY --from=builder /pg_ivm/output /
@@ -0,0 +1,49 @@
1
+ import { getConnection } from "../src/pg-connection.ts";
2
+ import { getMigrations } from "../migrations/system-version.ts";
3
+ import type { Client } from "pg";
4
+ import { insertPaimaEngineMigration } from "@effectstream/db";
5
+
6
+ export async function applyMigrations(
7
+ db: Client,
8
+ blockHeight: number,
9
+ name: string,
10
+ sql: string,
11
+ isSystemMigration: boolean,
12
+ ) {
13
+ console.log(
14
+ `[APPLY MIGRATION] Block height: ${blockHeight} | Migration: ${name}`,
15
+ );
16
+ await db.query(sql);
17
+ await insertPaimaEngineMigration.run(
18
+ {
19
+ name,
20
+ blockHeight,
21
+ isSystemMigration,
22
+ },
23
+ db,
24
+ );
25
+ }
26
+
27
+ // Functions for standalone execution
28
+ async function standAloneApplyInitialMigrations(
29
+ db: any, // Client,
30
+ blockHeight: number,
31
+ ) {
32
+ const migrations = await getMigrations();
33
+ for (const migration of migrations) {
34
+ await applyMigrations(
35
+ db,
36
+ blockHeight,
37
+ migration.version,
38
+ migration.sql,
39
+ true,
40
+ );
41
+ }
42
+ }
43
+
44
+ if (import.meta.main) {
45
+ const db = await getConnection();
46
+ await standAloneApplyInitialMigrations(db, 0);
47
+ console.log("✅ System migrations applied");
48
+ process.exit(0);
49
+ }
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env bun
2
+ import { spawn } from "node:child_process";
3
+ import { waitForDb } from "./wait-for-db.ts";
4
+ import { dirname, join } from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+
7
+ async function runPgtyped() {
8
+ try {
9
+ console.log("🔄 Running pgtyped...");
10
+ const __dirname = dirname(import.meta.url?.startsWith("file:") ? fileURLToPath(import.meta.url) : import.meta.url.replace("file://", ""));
11
+ const configPath = join(__dirname, "../pgtypedconfig.json");
12
+ const child = spawn("npx", ["pgtyped", "-c", configPath], {
13
+ stdio: "inherit",
14
+ shell: true,
15
+ });
16
+
17
+ const code = await new Promise<number | null>((resolve) => {
18
+ child.on("close", (code) => resolve(code));
19
+ });
20
+
21
+ if (code === 0) {
22
+ console.log("✅ pgtyped completed successfully");
23
+ } else {
24
+ console.error("❌ pgtyped failed");
25
+ process.exit(code ?? 1);
26
+ }
27
+ } catch (error) {
28
+ console.error("❌ Error running pgtyped:", error);
29
+ process.exit(1);
30
+ }
31
+ }
32
+
33
+ async function main() {
34
+ // First wait for the database
35
+ await waitForDb();
36
+
37
+ // Then run pgtyped
38
+ await runPgtyped();
39
+ }
40
+
41
+ if (import.meta.main) {
42
+ await main();
43
+ }