soltag 0.0.1
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.
- package/LICENSE +21 -0
- package/README.md +248 -0
- package/dist/chunk-LNEBK5MP.js +192 -0
- package/dist/chunk-LNEBK5MP.js.map +1 -0
- package/dist/esbuild.d.ts +7 -0
- package/dist/esbuild.js +10 -0
- package/dist/esbuild.js.map +1 -0
- package/dist/index.d.ts +95 -0
- package/dist/index.js +198 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin.cjs +391 -0
- package/dist/plugin.cjs.map +1 -0
- package/dist/rollup.d.ts +8 -0
- package/dist/rollup.js +10 -0
- package/dist/rollup.js.map +1 -0
- package/dist/unplugin.d.ts +19 -0
- package/dist/unplugin.js +11 -0
- package/dist/unplugin.js.map +1 -0
- package/dist/vite.d.ts +7 -0
- package/dist/vite.js +10 -0
- package/dist/vite.js.map +1 -0
- package/dist/webpack.d.ts +7 -0
- package/dist/webpack.js +10 -0
- package/dist/webpack.js.map +1 -0
- package/package.json +89 -0
- package/plugin.js +4 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 morpho-org
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
# soltag
|
|
2
|
+
|
|
3
|
+
Inline Solidity in TypeScript. Write Solidity inside a tagged template literal, get real-time IDE type inference, and execute deployless reads via `eth_call` + `stateOverride`.
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import { sol } from 'soltag';
|
|
7
|
+
|
|
8
|
+
const contract = sol`
|
|
9
|
+
pragma solidity ^0.8.24;
|
|
10
|
+
interface IERC20 { function balanceOf(address) external view returns (uint256); }
|
|
11
|
+
library Lens {
|
|
12
|
+
function userBalances(address[] memory tokens, address user)
|
|
13
|
+
external view returns (uint256[] memory out)
|
|
14
|
+
{
|
|
15
|
+
out = new uint256[](tokens.length);
|
|
16
|
+
for (uint256 i = 0; i < tokens.length; i++) {
|
|
17
|
+
out[i] = IERC20(tokens[i]).balanceOf(user);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
`;
|
|
22
|
+
|
|
23
|
+
const balances = await contract.call(client, 'userBalances', [[USDC, WETH], user]);
|
|
24
|
+
// ^? bigint[] ^? autocompletes ^? typed args
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Features
|
|
28
|
+
|
|
29
|
+
- **`sol` tagged template** — write Solidity inline, get a `SolContract` you can `.call()` against any RPC. Supports string interpolation for composing reusable fragments
|
|
30
|
+
- **Real-time IDE support** — function name autocomplete, typed args, return type hover, inline Solidity diagnostics via a TypeScript Language Service Plugin (no codegen)
|
|
31
|
+
- **Build-time compilation** — bundler plugin (Vite, Rollup, esbuild, webpack) compiles Solidity at build time so `solc` (8MB WASM) never ships to production
|
|
32
|
+
- **Deployless execution** — uses `eth_call` with `stateOverride` to run contract code without deploying
|
|
33
|
+
|
|
34
|
+
## Install
|
|
35
|
+
|
|
36
|
+
```sh
|
|
37
|
+
pnpm add soltag viem
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
For **runtime compilation** (scripts, REPLs, testing), also install `solc`:
|
|
41
|
+
|
|
42
|
+
```sh
|
|
43
|
+
pnpm add solc
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
For the **bundler plugin** (recommended for apps), install `solc` as a dev dependency along with `unplugin` and `magic-string`:
|
|
47
|
+
|
|
48
|
+
```sh
|
|
49
|
+
pnpm add -D solc unplugin magic-string
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
> **Note on `pragma solidity`:** The pragma in your Solidity source is a compatibility constraint checked by solc at compile time — it doesn't select a compiler version. As long as your installed `solc` version satisfies the pragma range (e.g. solc 0.8.28 satisfies `^0.8.24`), compilation proceeds. If it doesn't, solc will reject it with an error.
|
|
53
|
+
|
|
54
|
+
## Setup
|
|
55
|
+
|
|
56
|
+
### Bundler Plugin (recommended for apps)
|
|
57
|
+
|
|
58
|
+
Compiles `sol` templates at build time — `solc` is only needed during the build, not at runtime.
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
// vite.config.ts
|
|
62
|
+
import soltag from 'soltag/vite';
|
|
63
|
+
|
|
64
|
+
export default defineConfig({
|
|
65
|
+
plugins: [soltag()],
|
|
66
|
+
});
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Also available for other bundlers:
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
import soltag from 'soltag/rollup';
|
|
73
|
+
import soltag from 'soltag/esbuild';
|
|
74
|
+
import soltag from 'soltag/webpack';
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### TypeScript Plugin (IDE support)
|
|
78
|
+
|
|
79
|
+
Add to your `tsconfig.json` for autocomplete, hover types, and inline Solidity diagnostics:
|
|
80
|
+
|
|
81
|
+
```json
|
|
82
|
+
{
|
|
83
|
+
"compilerOptions": {
|
|
84
|
+
"plugins": [{ "name": "soltag/plugin" }]
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
> VS Code users: make sure your workspace is using the TypeScript version from `node_modules` (not the built-in one). Open a `.ts` file, click the TypeScript version in the bottom status bar, and select "Use Workspace Version".
|
|
90
|
+
|
|
91
|
+
## Usage
|
|
92
|
+
|
|
93
|
+
### Basic
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
import { sol } from 'soltag';
|
|
97
|
+
import { createPublicClient, http } from 'viem';
|
|
98
|
+
import { mainnet } from 'viem/chains';
|
|
99
|
+
|
|
100
|
+
const client = createPublicClient({ chain: mainnet, transport: http() });
|
|
101
|
+
|
|
102
|
+
const contract = sol`
|
|
103
|
+
pragma solidity ^0.8.24;
|
|
104
|
+
contract Math {
|
|
105
|
+
function add(uint256 a, uint256 b) external pure returns (uint256) {
|
|
106
|
+
return a + b;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
`;
|
|
110
|
+
|
|
111
|
+
const result = await contract.call(client, 'add', [1n, 2n]);
|
|
112
|
+
// result === 3n
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Reading on-chain state
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
const contract = sol`
|
|
119
|
+
pragma solidity ^0.8.24;
|
|
120
|
+
interface IERC20 {
|
|
121
|
+
function balanceOf(address) external view returns (uint256);
|
|
122
|
+
function decimals() external view returns (uint8);
|
|
123
|
+
}
|
|
124
|
+
library Lens {
|
|
125
|
+
function getBalance(address token, address user)
|
|
126
|
+
external view returns (uint256 balance, uint8 decimals)
|
|
127
|
+
{
|
|
128
|
+
balance = IERC20(token).balanceOf(user);
|
|
129
|
+
decimals = IERC20(token).decimals();
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
`;
|
|
133
|
+
|
|
134
|
+
const [balance, decimals] = await contract.call(client, 'getBalance', [USDC, user]);
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Composing with fragments
|
|
138
|
+
|
|
139
|
+
The `sol` tag supports string interpolation, so you can define reusable Solidity fragments and compose them:
|
|
140
|
+
|
|
141
|
+
```ts
|
|
142
|
+
const IERC20 = `
|
|
143
|
+
interface IERC20 {
|
|
144
|
+
function balanceOf(address) external view returns (uint256);
|
|
145
|
+
function decimals() external view returns (uint8);
|
|
146
|
+
}
|
|
147
|
+
`;
|
|
148
|
+
|
|
149
|
+
const balanceLens = sol`
|
|
150
|
+
pragma solidity ^0.8.24;
|
|
151
|
+
${IERC20}
|
|
152
|
+
contract BalanceLens {
|
|
153
|
+
function getBalance(address token, address user)
|
|
154
|
+
external view returns (uint256 balance, uint8 decimals)
|
|
155
|
+
{
|
|
156
|
+
balance = IERC20(token).balanceOf(user);
|
|
157
|
+
decimals = IERC20(token).decimals();
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
`;
|
|
161
|
+
|
|
162
|
+
const allowanceLens = sol`
|
|
163
|
+
pragma solidity ^0.8.24;
|
|
164
|
+
${IERC20}
|
|
165
|
+
contract AllowanceLens {
|
|
166
|
+
function getAllowance(address token, address owner, address spender)
|
|
167
|
+
external view returns (uint256)
|
|
168
|
+
{
|
|
169
|
+
return IERC20(token).allowance(owner, spender);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
`;
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
The bundler plugin resolves `const` string interpolations at build time, so these templates are still compiled ahead of time. Interpolations that can't be statically resolved (e.g. variables from function calls) are left for runtime compilation.
|
|
176
|
+
|
|
177
|
+
### Pre-compiled artifacts
|
|
178
|
+
|
|
179
|
+
For environments where you want full control over the compilation step:
|
|
180
|
+
|
|
181
|
+
```ts
|
|
182
|
+
import { SolContract } from 'soltag';
|
|
183
|
+
|
|
184
|
+
const contract = SolContract.fromArtifacts({
|
|
185
|
+
MyContract: {
|
|
186
|
+
abi: [/* ... */],
|
|
187
|
+
deployedBytecode: '0x...',
|
|
188
|
+
initBytecode: '0x...',
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## How It Works
|
|
194
|
+
|
|
195
|
+
### Runtime path (scripts, testing)
|
|
196
|
+
|
|
197
|
+
1. `sol` tag captures the Solidity source string
|
|
198
|
+
2. On first `.call()`, compiles with `solc-js` (lazy-loaded) and caches the result
|
|
199
|
+
3. Derives a deterministic address from the source hash
|
|
200
|
+
4. Executes via `eth_call` with `stateOverride` — the contract bytecode is injected at the derived address without deploying
|
|
201
|
+
5. Decodes the return value via viem's ABI decoder
|
|
202
|
+
|
|
203
|
+
### Build-time path (apps with bundler plugin)
|
|
204
|
+
|
|
205
|
+
1. The bundler plugin parses each file's AST to find `sol` tagged templates
|
|
206
|
+
2. For templates with interpolations, resolves `const` string values statically
|
|
207
|
+
3. Compiles the resolved Solidity with `solc-js` during the build
|
|
208
|
+
4. Replaces `` sol`...` `` with `SolContract.fromArtifacts({...})` containing the pre-compiled ABI and bytecode
|
|
209
|
+
5. At runtime, no compilation happens — only ABI encoding, `eth_call`, and decoding
|
|
210
|
+
|
|
211
|
+
### IDE path (TypeScript Language Service Plugin)
|
|
212
|
+
|
|
213
|
+
1. The TS plugin runs in `tsserver` (your editor's TypeScript process)
|
|
214
|
+
2. It finds `sol` tagged templates, compiles them with solc-js, and extracts the ABI
|
|
215
|
+
3. Provides function name completions for `.call()`, hover types showing Solidity-to-TypeScript mappings, and inline diagnostics for Solidity compilation errors
|
|
216
|
+
|
|
217
|
+
## API
|
|
218
|
+
|
|
219
|
+
### `sol`
|
|
220
|
+
|
|
221
|
+
```ts
|
|
222
|
+
function sol(strings: TemplateStringsArray, ...values: string[]): SolContract;
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Tagged template literal. Accepts string interpolations for composing Solidity from reusable fragments.
|
|
226
|
+
|
|
227
|
+
### `SolContract`
|
|
228
|
+
|
|
229
|
+
```ts
|
|
230
|
+
class SolContract {
|
|
231
|
+
// Create from pre-compiled artifacts (used by bundler plugin)
|
|
232
|
+
static fromArtifacts(artifacts: CompilationResult, sourceHash?: Hex): SolContract;
|
|
233
|
+
|
|
234
|
+
// Merged ABI across all contracts in the source
|
|
235
|
+
readonly abi: Abi;
|
|
236
|
+
|
|
237
|
+
// Execute a read-only call via stateOverride
|
|
238
|
+
call(client: PublicClient, functionName: string, args?: readonly unknown[]): Promise<unknown>;
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### `SolCompilationError`
|
|
243
|
+
|
|
244
|
+
Thrown when Solidity compilation fails. Contains a `.errors` array of `SolcDiagnostic` objects with severity, message, and source location.
|
|
245
|
+
|
|
246
|
+
## License
|
|
247
|
+
|
|
248
|
+
MIT
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
// src/build/unplugin.ts
|
|
2
|
+
import MagicString from "magic-string";
|
|
3
|
+
import ts from "typescript";
|
|
4
|
+
import { createUnplugin } from "unplugin";
|
|
5
|
+
|
|
6
|
+
// src/runtime/compiler.ts
|
|
7
|
+
import { createRequire } from "module";
|
|
8
|
+
import { keccak256, toHex } from "viem";
|
|
9
|
+
|
|
10
|
+
// src/solc.ts
|
|
11
|
+
function buildSolcInput(source) {
|
|
12
|
+
return {
|
|
13
|
+
language: "Solidity",
|
|
14
|
+
sources: {
|
|
15
|
+
"inline.sol": { content: source }
|
|
16
|
+
},
|
|
17
|
+
settings: {
|
|
18
|
+
optimizer: { enabled: true, runs: 1 },
|
|
19
|
+
outputSelection: {
|
|
20
|
+
"*": {
|
|
21
|
+
"*": ["abi", "evm.bytecode.object", "evm.deployedBytecode.object"]
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// src/runtime/compiler.ts
|
|
29
|
+
var require2 = createRequire(import.meta.url);
|
|
30
|
+
var solcInstance;
|
|
31
|
+
function getSolc() {
|
|
32
|
+
if (!solcInstance) {
|
|
33
|
+
try {
|
|
34
|
+
solcInstance = require2("solc");
|
|
35
|
+
} catch {
|
|
36
|
+
throw new Error(
|
|
37
|
+
"solc is not installed. Install it (`pnpm add solc`) for runtime compilation, or use the soltag bundler plugin for build-time compilation."
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return solcInstance;
|
|
42
|
+
}
|
|
43
|
+
var SolCompilationError = class extends Error {
|
|
44
|
+
constructor(errors) {
|
|
45
|
+
const formatted = errors.map((e) => `${e.severity}: ${e.message}`).join("\n");
|
|
46
|
+
super(`Solidity compilation failed:
|
|
47
|
+
${formatted}`);
|
|
48
|
+
this.errors = errors;
|
|
49
|
+
this.name = "SolCompilationError";
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
var compilationCache = /* @__PURE__ */ new Map();
|
|
53
|
+
function hashSource(source) {
|
|
54
|
+
return keccak256(toHex(source));
|
|
55
|
+
}
|
|
56
|
+
function compile(source) {
|
|
57
|
+
const hash = hashSource(source);
|
|
58
|
+
const cached = compilationCache.get(hash);
|
|
59
|
+
if (cached) return cached;
|
|
60
|
+
const solc = getSolc();
|
|
61
|
+
const input = buildSolcInput(source);
|
|
62
|
+
const rawOutput = solc.compile(JSON.stringify(input));
|
|
63
|
+
const output = JSON.parse(rawOutput);
|
|
64
|
+
const diagnostics = toDiagnostics(output.errors);
|
|
65
|
+
const errors = diagnostics.filter((d) => d.severity === "error");
|
|
66
|
+
if (errors.length > 0) {
|
|
67
|
+
throw new SolCompilationError(errors);
|
|
68
|
+
}
|
|
69
|
+
const result = {};
|
|
70
|
+
if (output.contracts) {
|
|
71
|
+
for (const [, fileContracts] of Object.entries(output.contracts)) {
|
|
72
|
+
for (const [contractName, contractOutput] of Object.entries(fileContracts)) {
|
|
73
|
+
result[contractName] = {
|
|
74
|
+
abi: contractOutput.abi,
|
|
75
|
+
deployedBytecode: `0x${contractOutput.evm.deployedBytecode.object}`,
|
|
76
|
+
initBytecode: `0x${contractOutput.evm.bytecode.object}`
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
compilationCache.set(hash, result);
|
|
82
|
+
return result;
|
|
83
|
+
}
|
|
84
|
+
function toDiagnostics(errors) {
|
|
85
|
+
return (errors ?? []).map((e) => ({
|
|
86
|
+
severity: e.severity,
|
|
87
|
+
message: e.message,
|
|
88
|
+
formattedMessage: e.formattedMessage,
|
|
89
|
+
sourceLocation: e.sourceLocation
|
|
90
|
+
}));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// src/build/unplugin.ts
|
|
94
|
+
function resolveStringExpression(node, sourceFile) {
|
|
95
|
+
if (ts.isStringLiteral(node)) return node.text;
|
|
96
|
+
if (ts.isNoSubstitutionTemplateLiteral(node)) return node.text;
|
|
97
|
+
if (ts.isTemplateExpression(node)) {
|
|
98
|
+
let result = node.head.text;
|
|
99
|
+
for (const span of node.templateSpans) {
|
|
100
|
+
const resolved = resolveStringExpression(span.expression, sourceFile);
|
|
101
|
+
if (resolved === void 0) return void 0;
|
|
102
|
+
result += resolved + span.literal.text;
|
|
103
|
+
}
|
|
104
|
+
return result;
|
|
105
|
+
}
|
|
106
|
+
if (ts.isIdentifier(node)) {
|
|
107
|
+
return resolveIdentifierToString(node, sourceFile);
|
|
108
|
+
}
|
|
109
|
+
if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.PlusToken) {
|
|
110
|
+
const left = resolveStringExpression(node.left, sourceFile);
|
|
111
|
+
const right = resolveStringExpression(node.right, sourceFile);
|
|
112
|
+
if (left !== void 0 && right !== void 0) return left + right;
|
|
113
|
+
return void 0;
|
|
114
|
+
}
|
|
115
|
+
return void 0;
|
|
116
|
+
}
|
|
117
|
+
function resolveIdentifierToString(identifier, sourceFile) {
|
|
118
|
+
const name = identifier.text;
|
|
119
|
+
for (const statement of sourceFile.statements) {
|
|
120
|
+
if (!ts.isVariableStatement(statement)) continue;
|
|
121
|
+
if (!(statement.declarationList.flags & ts.NodeFlags.Const)) continue;
|
|
122
|
+
for (const decl of statement.declarationList.declarations) {
|
|
123
|
+
if (ts.isIdentifier(decl.name) && decl.name.text === name && decl.initializer) {
|
|
124
|
+
return resolveStringExpression(decl.initializer, sourceFile);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return void 0;
|
|
129
|
+
}
|
|
130
|
+
function extractTemplateSource(template, sourceFile) {
|
|
131
|
+
if (ts.isNoSubstitutionTemplateLiteral(template)) {
|
|
132
|
+
return template.text;
|
|
133
|
+
}
|
|
134
|
+
let result = template.head.text;
|
|
135
|
+
for (const span of template.templateSpans) {
|
|
136
|
+
const resolved = resolveStringExpression(span.expression, sourceFile);
|
|
137
|
+
if (resolved === void 0) return void 0;
|
|
138
|
+
result += resolved + span.literal.text;
|
|
139
|
+
}
|
|
140
|
+
return result;
|
|
141
|
+
}
|
|
142
|
+
function transformSolTemplates(code, id) {
|
|
143
|
+
if (!code.includes("sol`") && !code.includes("sol `")) return void 0;
|
|
144
|
+
const sourceFile = ts.createSourceFile(id, code, ts.ScriptTarget.Latest, true);
|
|
145
|
+
const s = new MagicString(code);
|
|
146
|
+
let hasReplacements = false;
|
|
147
|
+
function visit(node) {
|
|
148
|
+
if (ts.isTaggedTemplateExpression(node) && ts.isIdentifier(node.tag) && node.tag.text === "sol") {
|
|
149
|
+
const soliditySource = extractTemplateSource(node.template, sourceFile);
|
|
150
|
+
if (soliditySource === void 0) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
const artifacts = compile(soliditySource);
|
|
154
|
+
const sourceHash = hashSource(soliditySource);
|
|
155
|
+
const replacement = `__SolContract.fromArtifacts(${JSON.stringify(artifacts)}, "${sourceHash}")`;
|
|
156
|
+
s.overwrite(node.getStart(sourceFile), node.getEnd(), replacement);
|
|
157
|
+
hasReplacements = true;
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
ts.forEachChild(node, visit);
|
|
161
|
+
}
|
|
162
|
+
visit(sourceFile);
|
|
163
|
+
if (!hasReplacements) return void 0;
|
|
164
|
+
s.prepend('import { SolContract as __SolContract } from "soltag";\n');
|
|
165
|
+
return {
|
|
166
|
+
code: s.toString(),
|
|
167
|
+
map: s.generateMap({ source: id, hires: true })
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
var unplugin = createUnplugin((options) => {
|
|
171
|
+
const include = options?.include ?? [".ts", ".tsx", ".mts", ".cts"];
|
|
172
|
+
const exclude = options?.exclude ?? [/node_modules/];
|
|
173
|
+
return {
|
|
174
|
+
name: "soltag",
|
|
175
|
+
enforce: "pre",
|
|
176
|
+
transformInclude(id) {
|
|
177
|
+
if (exclude.some((e) => e.test(id))) return false;
|
|
178
|
+
return include.some((ext) => id.endsWith(ext));
|
|
179
|
+
},
|
|
180
|
+
transform(code, id) {
|
|
181
|
+
return transformSolTemplates(code, id);
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
});
|
|
185
|
+
var unplugin_default = unplugin;
|
|
186
|
+
|
|
187
|
+
export {
|
|
188
|
+
transformSolTemplates,
|
|
189
|
+
unplugin,
|
|
190
|
+
unplugin_default
|
|
191
|
+
};
|
|
192
|
+
//# sourceMappingURL=chunk-LNEBK5MP.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/build/unplugin.ts","../src/runtime/compiler.ts","../src/solc.ts"],"sourcesContent":["import MagicString from \"magic-string\";\nimport ts from \"typescript\";\nimport { createUnplugin } from \"unplugin\";\n\nimport { compile, hashSource } from \"../runtime/compiler.js\";\n\nexport interface SoltagPluginOptions {\n /** Extra file extensions to include. Defaults to ['.ts', '.tsx', '.mts', '.cts'] */\n include?: string[];\n /** Patterns to exclude. Defaults to [/node_modules/] */\n exclude?: RegExp[];\n}\n\n/**\n * Try to resolve a TS expression to a string constant at build time.\n * Returns the resolved string, or undefined if the expression can't be statically resolved.\n */\nfunction resolveStringExpression(node: ts.Expression, sourceFile: ts.SourceFile): string | undefined {\n if (ts.isStringLiteral(node)) return node.text;\n\n if (ts.isNoSubstitutionTemplateLiteral(node)) return node.text;\n\n if (ts.isTemplateExpression(node)) {\n let result = node.head.text;\n for (const span of node.templateSpans) {\n const resolved = resolveStringExpression(span.expression, sourceFile);\n if (resolved === undefined) return undefined;\n result += resolved + span.literal.text;\n }\n return result;\n }\n\n if (ts.isIdentifier(node)) {\n return resolveIdentifierToString(node, sourceFile);\n }\n\n // String concatenation with +\n if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.PlusToken) {\n const left = resolveStringExpression(node.left, sourceFile);\n const right = resolveStringExpression(node.right, sourceFile);\n if (left !== undefined && right !== undefined) return left + right;\n return undefined;\n }\n\n return undefined;\n}\n\n/**\n * Find a const declaration for an identifier and resolve its string value.\n */\nfunction resolveIdentifierToString(identifier: ts.Identifier, sourceFile: ts.SourceFile): string | undefined {\n const name = identifier.text;\n\n for (const statement of sourceFile.statements) {\n if (!ts.isVariableStatement(statement)) continue;\n if (!(statement.declarationList.flags & ts.NodeFlags.Const)) continue;\n\n for (const decl of statement.declarationList.declarations) {\n if (ts.isIdentifier(decl.name) && decl.name.text === name && decl.initializer) {\n return resolveStringExpression(decl.initializer, sourceFile);\n }\n }\n }\n\n return undefined;\n}\n\n/**\n * Extract the full Solidity source from a tagged template, resolving interpolations.\n * Returns undefined if any interpolation can't be statically resolved.\n */\nfunction extractTemplateSource(template: ts.TemplateLiteral, sourceFile: ts.SourceFile): string | undefined {\n if (ts.isNoSubstitutionTemplateLiteral(template)) {\n return template.text;\n }\n\n let result = template.head.text;\n for (const span of template.templateSpans) {\n const resolved = resolveStringExpression(span.expression, sourceFile);\n if (resolved === undefined) return undefined;\n result += resolved + span.literal.text;\n }\n return result;\n}\n\n/**\n * Core transform logic, exported for testing.\n */\nexport function transformSolTemplates(\n code: string,\n id: string,\n): { code: string; map: ReturnType<MagicString[\"generateMap\"]> } | undefined {\n if (!code.includes(\"sol`\") && !code.includes(\"sol `\")) return undefined;\n\n const sourceFile = ts.createSourceFile(id, code, ts.ScriptTarget.Latest, true);\n const s = new MagicString(code);\n let hasReplacements = false;\n\n function visit(node: ts.Node) {\n if (ts.isTaggedTemplateExpression(node) && ts.isIdentifier(node.tag) && node.tag.text === \"sol\") {\n const soliditySource = extractTemplateSource(node.template, sourceFile);\n if (soliditySource === undefined) {\n // Can't resolve at build time — leave for runtime\n return;\n }\n\n const artifacts = compile(soliditySource);\n const sourceHash = hashSource(soliditySource);\n\n const replacement = `__SolContract.fromArtifacts(${JSON.stringify(artifacts)}, \"${sourceHash}\")`;\n s.overwrite(node.getStart(sourceFile), node.getEnd(), replacement);\n hasReplacements = true;\n return; // Don't visit children\n }\n\n ts.forEachChild(node, visit);\n }\n\n visit(sourceFile);\n\n if (!hasReplacements) return undefined;\n\n s.prepend('import { SolContract as __SolContract } from \"soltag\";\\n');\n\n return {\n code: s.toString(),\n map: s.generateMap({ source: id, hires: true }),\n };\n}\n\nexport const unplugin = createUnplugin((options?: SoltagPluginOptions) => {\n const include = options?.include ?? [\".ts\", \".tsx\", \".mts\", \".cts\"];\n const exclude = options?.exclude ?? [/node_modules/];\n\n return {\n name: \"soltag\",\n enforce: \"pre\" as const,\n\n transformInclude(id: string) {\n if (exclude.some((e) => e.test(id))) return false;\n return include.some((ext) => id.endsWith(ext));\n },\n\n transform(code: string, id: string) {\n return transformSolTemplates(code, id);\n },\n };\n});\n\nexport default unplugin;\n","import { createRequire } from \"node:module\";\n\nimport { type Abi, type Hex, keccak256, toHex } from \"viem\";\n\nimport { buildSolcInput, type SolcError, type SolcModule, type SolcStandardOutput } from \"../solc.js\";\n\nconst require = createRequire(import.meta.url);\n\nlet solcInstance: SolcModule | undefined;\n\nfunction getSolc(): SolcModule {\n if (!solcInstance) {\n try {\n solcInstance = require(\"solc\") as SolcModule;\n } catch {\n throw new Error(\n \"solc is not installed. Install it (`pnpm add solc`) for runtime compilation, \" +\n \"or use the soltag bundler plugin for build-time compilation.\",\n );\n }\n }\n return solcInstance;\n}\n\nexport type { SolcAbiItem, SolcAbiParam } from \"../solc.js\";\n\nexport interface CompiledContract {\n abi: Abi;\n /** Runtime bytecode (what lives at the contract address). Used with stateOverride. */\n deployedBytecode: Hex;\n /** Init bytecode (constructor + deployment code). Used for actual deployment. */\n initBytecode: Hex;\n}\n\nexport type CompilationResult = Record<string, CompiledContract>;\n\nexport interface SolcDiagnostic {\n severity: \"error\" | \"warning\";\n message: string;\n formattedMessage: string;\n sourceLocation?: {\n file: string;\n start: number;\n end: number;\n };\n}\n\nexport class SolCompilationError extends Error {\n constructor(public readonly errors: SolcDiagnostic[]) {\n const formatted = errors.map((e) => `${e.severity}: ${e.message}`).join(\"\\n\");\n super(`Solidity compilation failed:\\n${formatted}`);\n this.name = \"SolCompilationError\";\n }\n}\n\n// Cache compiled results by source hash\nconst compilationCache = new Map<string, CompilationResult>();\n\nexport function hashSource(source: string): Hex {\n return keccak256(toHex(source));\n}\n\nexport function compile(source: string): CompilationResult {\n const hash = hashSource(source);\n const cached = compilationCache.get(hash);\n if (cached) return cached;\n\n const solc = getSolc();\n const input = buildSolcInput(source);\n const rawOutput = solc.compile(JSON.stringify(input));\n const output = JSON.parse(rawOutput) as SolcStandardOutput;\n\n const diagnostics = toDiagnostics(output.errors);\n const errors = diagnostics.filter((d) => d.severity === \"error\");\n if (errors.length > 0) {\n throw new SolCompilationError(errors);\n }\n\n const result: CompilationResult = {};\n\n if (output.contracts) {\n for (const [, fileContracts] of Object.entries(output.contracts)) {\n for (const [contractName, contractOutput] of Object.entries(fileContracts)) {\n result[contractName] = {\n abi: contractOutput.abi as Abi,\n deployedBytecode: `0x${contractOutput.evm.deployedBytecode.object}` as Hex,\n initBytecode: `0x${contractOutput.evm.bytecode.object}` as Hex,\n };\n }\n }\n }\n\n compilationCache.set(hash, result);\n return result;\n}\n\nfunction toDiagnostics(errors: SolcError[] | undefined): SolcDiagnostic[] {\n return (errors ?? []).map((e) => ({\n severity: e.severity as \"error\" | \"warning\",\n message: e.message,\n formattedMessage: e.formattedMessage,\n sourceLocation: e.sourceLocation,\n }));\n}\n","/**\n * Shared solc-js types and helpers used by both the runtime compiler\n * and the LS plugin cache.\n */\n\nexport interface SolcModule {\n compile(input: string): string;\n}\n\n/**\n * Build the standard JSON input object for solc.\n */\nexport function buildSolcInput(source: string) {\n return {\n language: \"Solidity\" as const,\n sources: {\n \"inline.sol\": { content: source },\n },\n settings: {\n optimizer: { enabled: true, runs: 1 },\n outputSelection: {\n \"*\": {\n \"*\": [\"abi\", \"evm.bytecode.object\", \"evm.deployedBytecode.object\"],\n },\n },\n },\n };\n}\n\n// --- solc standard output types ---\n\nexport interface SolcStandardOutput {\n contracts?: Record<string, Record<string, SolcContractOutput>>;\n errors?: SolcError[];\n}\n\nexport interface SolcContractOutput {\n abi: SolcAbiItem[];\n evm: {\n bytecode: { object: string };\n deployedBytecode: { object: string };\n };\n}\n\nexport interface SolcAbiItem {\n type: string;\n name?: string;\n inputs?: SolcAbiParam[];\n outputs?: SolcAbiParam[];\n stateMutability?: string;\n}\n\nexport interface SolcAbiParam {\n name: string;\n type: string;\n components?: SolcAbiParam[];\n internalType?: string;\n}\n\nexport interface SolcError {\n severity: string;\n message: string;\n formattedMessage: string;\n sourceLocation?: {\n file: string;\n start: number;\n end: number;\n };\n}\n"],"mappings":"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","names":["require"]}
|
package/dist/esbuild.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/build/esbuild.ts"],"sourcesContent":["import { unplugin } from \"./unplugin.js\";\nexport default unplugin.esbuild;\n"],"mappings":";;;;;AACA,IAAO,kBAAQ,SAAS;","names":[]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { Abi, Hex, PublicClient } from 'viem';
|
|
2
|
+
|
|
3
|
+
interface SolcAbiItem {
|
|
4
|
+
type: string;
|
|
5
|
+
name?: string;
|
|
6
|
+
inputs?: SolcAbiParam[];
|
|
7
|
+
outputs?: SolcAbiParam[];
|
|
8
|
+
stateMutability?: string;
|
|
9
|
+
}
|
|
10
|
+
interface SolcAbiParam {
|
|
11
|
+
name: string;
|
|
12
|
+
type: string;
|
|
13
|
+
components?: SolcAbiParam[];
|
|
14
|
+
internalType?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface CompiledContract {
|
|
18
|
+
abi: Abi;
|
|
19
|
+
/** Runtime bytecode (what lives at the contract address). Used with stateOverride. */
|
|
20
|
+
deployedBytecode: Hex;
|
|
21
|
+
/** Init bytecode (constructor + deployment code). Used for actual deployment. */
|
|
22
|
+
initBytecode: Hex;
|
|
23
|
+
}
|
|
24
|
+
type CompilationResult = Record<string, CompiledContract>;
|
|
25
|
+
interface SolcDiagnostic {
|
|
26
|
+
severity: "error" | "warning";
|
|
27
|
+
message: string;
|
|
28
|
+
formattedMessage: string;
|
|
29
|
+
sourceLocation?: {
|
|
30
|
+
file: string;
|
|
31
|
+
start: number;
|
|
32
|
+
end: number;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
declare class SolCompilationError extends Error {
|
|
36
|
+
readonly errors: SolcDiagnostic[];
|
|
37
|
+
constructor(errors: SolcDiagnostic[]);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
declare class SolContract {
|
|
41
|
+
private _source;
|
|
42
|
+
private _compiled;
|
|
43
|
+
private _address;
|
|
44
|
+
private _abi;
|
|
45
|
+
constructor(source: string);
|
|
46
|
+
/**
|
|
47
|
+
* Create a SolContract from pre-compiled artifacts.
|
|
48
|
+
* Used by the bundler plugin to bypass runtime solc compilation.
|
|
49
|
+
*
|
|
50
|
+
* @param artifacts - Pre-compiled contract artifacts (ABI + bytecode per contract name)
|
|
51
|
+
* @param sourceHash - keccak256 of the original Solidity source, for deterministic address derivation
|
|
52
|
+
*/
|
|
53
|
+
static fromArtifacts(artifacts: CompilationResult, sourceHash?: Hex): SolContract;
|
|
54
|
+
private ensureCompiled;
|
|
55
|
+
private getAddress;
|
|
56
|
+
get abi(): Abi;
|
|
57
|
+
call(client: PublicClient, functionName: string, args?: readonly unknown[]): Promise<unknown>;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Tagged template literal for inline Solidity.
|
|
62
|
+
*
|
|
63
|
+
* Usage:
|
|
64
|
+
* ```ts
|
|
65
|
+
* const contract = sol`
|
|
66
|
+
* pragma solidity ^0.8.24;
|
|
67
|
+
* contract Greeter {
|
|
68
|
+
* function greet() external pure returns (string memory) {
|
|
69
|
+
* return "hello";
|
|
70
|
+
* }
|
|
71
|
+
* }
|
|
72
|
+
* `;
|
|
73
|
+
* ```
|
|
74
|
+
*
|
|
75
|
+
* String interpolation is supported for composing Solidity from reusable fragments:
|
|
76
|
+
* ```ts
|
|
77
|
+
* const IERC20 = `
|
|
78
|
+
* interface IERC20 {
|
|
79
|
+
* function balanceOf(address) external view returns (uint256);
|
|
80
|
+
* }
|
|
81
|
+
* `;
|
|
82
|
+
*
|
|
83
|
+
* const contract = sol`
|
|
84
|
+
* ${IERC20}
|
|
85
|
+
* contract Lens {
|
|
86
|
+
* function getBalance(address token, address user) external view returns (uint256) {
|
|
87
|
+
* return IERC20(token).balanceOf(user);
|
|
88
|
+
* }
|
|
89
|
+
* }
|
|
90
|
+
* `;
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
declare function sol(strings: TemplateStringsArray, ...values: string[]): SolContract;
|
|
94
|
+
|
|
95
|
+
export { type CompilationResult, type CompiledContract, SolCompilationError, SolContract, type SolcAbiItem, type SolcAbiParam, type SolcDiagnostic, sol };
|