1
1
import { readFileSync } from "fs" ;
2
2
import { DeployOpts } from "./model" ;
3
- import { TextDecoder , TextEncoder } from "util" ;
4
3
import { ContractType , Tag } from "../../../common/model" ;
5
4
import { em } from "../em-wrapper" ;
6
5
import { error } from "../../utils/common" ;
7
6
import { figureOutContractType } from "../../../common/utils/commons" ;
8
7
9
- const Arweave = require ( 'arweave' ) ;
10
- const Confirm = require ( 'prompt-confirm' ) ;
11
-
12
- const Encoder = new TextEncoder ( ) ;
13
- const Decoder = new TextDecoder ( ) ;
14
-
15
- const initContract = async ( initState : string , contractTxId : string , wallet : any , arweave : typeof Arweave ) => {
16
- const tx = await arweave . createTransaction ( {
17
- data : Encoder . encode ( initState ) ,
18
- } ) ;
19
-
20
- tx . addTag ( "Contract-Src" , contractTxId ) ;
21
- await arweave . transactions . sign ( tx , wallet ) ;
22
8
23
- return [ tx , {
24
- id : tx . id ,
25
- tags : tx . tags . map ( ( { name, value } : Tag ) => ( {
26
- name : atob ( name ) ,
27
- value : atob ( value ) ,
28
- } ) ) ,
29
- data : Decoder . decode ( tx . data ) ,
30
- } ] ;
31
- }
32
-
33
- const successfulDeployment = ( sourceTxId : string , initTxId : string ) => {
34
- console . log ( "Function deployed 🎉\n" ) ;
35
- console . log ( `EXM Function ID: ${ initTxId } ` ) ;
36
- console . log ( "EXM Function Source Code:" , "https://arweave.net/tx/" + sourceTxId ) ;
37
- console . log ( "EXM Function:" , "https://arweave.net/tx/" + initTxId ) ;
38
- console . log ( `\nUse Function Id ${ initTxId } as your interaction reference.` ) ;
39
- }
9
+ const Confirm = require ( 'prompt-confirm' ) ;
10
+ const chalk = require ( 'chalk' ) ;
11
+
12
+ const boxMarks = {
13
+ nw : '╭' ,
14
+ n : '─' ,
15
+ ne : '╮' ,
16
+ e : '│' ,
17
+ se : '╯' ,
18
+ s : '─' ,
19
+ sw : '╰' ,
20
+ w : '│'
21
+ } ;
40
22
41
23
export const functionDeployCmd = async ( opts : DeployOpts ) => {
42
24
let contentType : ContractType = figureOutContractType ( opts . type || opts . src , opts . type !== undefined ) ;
@@ -50,113 +32,65 @@ export const functionDeployCmd = async (opts: DeployOpts) => {
50
32
error ( `Deployment requires --init-state or --init-state-src to be passed` ) ;
51
33
}
52
34
53
- if ( opts . useArweave === true ) {
54
- const arweave = Arweave . init ( {
55
- host : "arweave.net" ,
56
- port : 443 ,
57
- protocol : "https" ,
58
- } ) ;
59
-
60
- if ( ! opts . wallet ) {
61
- error ( '--wallet (Wallet Path) is required for deployments' ) ;
62
- }
63
-
64
- const wallet = JSON . parse ( readFileSync ( opts . wallet , 'utf8' ) ) ;
65
- const address : string = await arweave . wallets . jwkToAddress ( wallet ) ;
66
- console . log ( "Deploying function using wallet" , address ) ;
67
-
68
- if ( opts . contractTx ) {
69
- console . log ( "Deploying contract using source transaction" , opts . contractTx ) ;
70
-
71
- const initDeploymentTx = await initContract ( initState , opts . contractTx , wallet , arweave ) ;
72
- console . log ( "\nInit Function:" , initDeploymentTx [ 1 ] ) ;
73
-
74
- const doDeploy = await new Confirm ( 'Do you want to deploy this function?' ) . run ( ) ;
75
-
76
- if ( doDeploy ) {
77
- const res = await arweave . transactions . post ( initDeploymentTx [ 0 ] ) ;
78
- if ( res . status >= 400 ) {
79
- error ( `Failed to deploy init Function. Source Function ID: ${ opts . contractTx } ` ) ;
80
- }
35
+ let contractData : Uint8Array ;
81
36
82
- successfulDeployment ( opts . contractTx , initDeploymentTx [ 1 ] . id ) ;
83
- } else {
84
- console . log ( "\nDeployment cancelled" ) ;
85
- }
86
- } else if ( opts . src ) {
87
- // Source Contract
88
- const txSource = await arweave . createTransaction ( {
89
- data : readFileSync ( opts . src ) ,
90
- } ) ;
91
- txSource . addTag ( "Content-Type" , contentType ) ;
92
- txSource . addTag ( "App-Name" , "EM" ) ;
93
- txSource . addTag ( "Type" , "Serverless-Function" ) ;
94
- await arweave . transactions . sign ( txSource , wallet ) ;
95
-
96
- // Init Contract
97
- const txInit = await initContract ( initState , txSource . id , wallet , arweave ) ;
98
-
99
- console . log ( `\nSource Contract:` , {
100
- id : txSource . id ,
101
- tags : txSource . tags . map ( ( { name, value} : { [ x : string ] : string } ) => ( {
102
- name : atob ( name ) ,
103
- value : atob ( value ) ,
104
- } ) )
105
- } ) ;
106
-
107
- console . log ( `\nInit Contract` , txInit [ 1 ] ) ;
108
-
109
- const confirmation = await new Confirm ( 'Do you want to deploy this function?' ) . run ( ) ;
110
-
111
- if ( confirmation ) {
112
- const txSourceDeployment = await arweave . transactions . post ( txSource ) ;
113
- if ( txSourceDeployment . status >= 400 ) {
114
- error ( `Failed to deploy source contract.` ) ;
115
- } else {
116
- const initContractDeployment = await arweave . transactions . post ( txInit [ 0 ] ) ;
117
- if ( initContractDeployment . status >= 400 ) {
118
- error ( `Failed to init function. Source function ID: ${ txSource . id } ` ) ;
119
- }
120
- }
37
+ if ( ! opts . token ) {
38
+ error ( 'EXM Token (--token) is required to deploy functions through EXM' ) ;
39
+ }
121
40
122
- successfulDeployment ( txSource . id , txInit [ 1 ] . id ) ;
123
- } else {
124
- console . log ( "\nDeployment cancelled" ) ;
125
- }
41
+ if ( opts . contractTx ) {
42
+ const fetchContractSourceTx = await fetch ( `https://arweave.net/ ${ opts . contractTx } ` ) ;
43
+ if ( fetchContractSourceTx . ok ) {
44
+ contractData = new Uint8Array ( await fetchContractSourceTx . arrayBuffer ( ) ) ;
126
45
} else {
127
- error ( `Deployment requires --contract-tx or --src ` ) ;
46
+ console . error ( `Source function transaction ${ opts . contractTx } is invalid or does not exist. ` ) ;
128
47
}
48
+ } else if ( opts . src ) {
49
+ contractData = await readFileSync ( opts . src ) ;
129
50
} else {
130
- let contractData : Uint8Array ;
51
+ error ( `Deployment requires --contract-tx or --src` ) ;
52
+ }
131
53
132
- if ( ! opts . token ) {
133
- error ( 'EXM Token (--token) is required to deploy functions through EXM' ) ;
134
- }
54
+ const confirmation = await new Confirm ( `Do you want to deploy this function?` ) . run ( ) ;
55
+ if ( confirmation ) {
135
56
136
- if ( opts . contractTx ) {
137
- const fetchContractSourceTx = await fetch ( `https://arweave.net/${ opts . contractTx } ` ) ;
138
- if ( fetchContractSourceTx . ok ) {
139
- contractData = new Uint8Array ( await fetchContractSourceTx . arrayBuffer ( ) ) ;
140
- } else {
141
- console . error ( `Source function transaction ${ opts . contractTx } is invalid or does not exist.` ) ;
142
- }
143
- } else if ( opts . src ) {
144
- contractData = await readFileSync ( opts . src ) ;
145
- } else {
146
- error ( `Deployment requires --contract-tx or --src` ) ;
57
+ if ( opts . token ) {
58
+ em . changeToken ( opts . token ) ;
147
59
}
148
60
149
- const confirmation = await new Confirm ( `Do you want to deploy this function?` ) . run ( ) ;
150
- if ( confirmation ) {
151
-
152
- if ( opts . token ) {
153
- em . changeToken ( opts . token ) ;
154
- }
155
-
156
- const beginDeployment = await em . functions . deploy ( contractData , initState , contentType ) ;
157
- console . log ( `Function deployed 🎉\n` ) ;
158
- console . log ( `EXM Function ID: ${ beginDeployment . id } ` ) ;
159
- console . log ( `EXM Function: https://arweave.net/${ beginDeployment . id } ` ) ;
160
- }
61
+ const Box = require ( 'cli-box' ) ;
62
+ const beginDeployment = await em . functions . deploy ( contractData , initState , contentType ) ;
63
+
64
+ const resultBox = new Box ( {
65
+ w : 100 ,
66
+ h : 4 ,
67
+ stringify : false ,
68
+ marks : boxMarks ,
69
+ hAlign : 'left' ,
70
+ vAlign : 'top'
71
+ } , `Function deployed 🎉
72
+ ▸ EXM Function ID : ${ beginDeployment . id }
73
+ ▸ EXM Function Source : https://arweave.net/${ beginDeployment . id }
74
+ ▸ Function URL : https://${ beginDeployment . id } .exm.run` ) ;
75
+
76
+ console . log ( resultBox . stringify ( ) ) ;
77
+
78
+ const functionUrlExample = new Box ( {
79
+ w : 100 ,
80
+ h : 8 ,
81
+ stringify : false ,
82
+ marks : boxMarks ,
83
+ hAlign : 'left' ,
84
+ vAlign : 'top'
85
+ } , `${ chalk . blue ( 'Id: ' ) } ${ beginDeployment . id }
86
+
87
+ curl --location --request POST 'https://${ beginDeployment . id } .exm.run'
88
+ --header 'Content-Type: application/json'
89
+ --data-raw '{}' ${ chalk . blue ( '<= Any JSON body' ) }
90
+
91
+ Documentation: https://docs.exm.dev/trustless-serverless-functions/function-urls
92
+ ` ) ;
93
+
94
+ console . log ( functionUrlExample . stringify ( ) ) ;
161
95
}
162
96
}
0 commit comments