@terminal3/t3n-sdk 1.3.2 → 2.3.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.
package/README.md CHANGED
@@ -86,6 +86,88 @@ const oidcCredentials = {
86
86
  const did = await client.authenticate(createOidcAuthInput(oidcCredentials));
87
87
  ```
88
88
 
89
+ ## Migrating from 1.x
90
+
91
+ `@terminal3/t3n-sdk@2.0.0` cuts over to `tee:user/contracts@2.0.0`
92
+ (MAT-1374). The implicit-dispatch monolith `user-upsert` on the user
93
+ contract was split into three explicit functions on the same
94
+ contract:
95
+
96
+ - `otp-request` — request + dispatch an OTP code.
97
+ - `otp-verify` — redeem an OTP and bind the contact.
98
+ - `user-upsert` (slim) — Level 1 user-input ingest only. Rejects
99
+ callers without a verified email with the typed
100
+ `UserUpsertError { kind: "EmailNotVerified" }` (wire form
101
+ `email_not_verified:<detail>`).
102
+
103
+ If you used the typed `T3nClient` methods to wrap `executeAction`,
104
+ the SDK now ships `client.otpRequest` / `client.otpVerify` /
105
+ `client.submitUserInput` (plus a convenience
106
+ `client.runOtpThenUserInput`) so you can migrate one call site at a
107
+ time:
108
+
109
+ | Pre-2.0.0 (`tee:user@1.5.0`) | 2.x (`tee:user@2.0.0`, contract ≥ 2.1.0 for discriminated OTP) |
110
+ | ---------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
111
+ | `executeAction({ function_name: "user-upsert", input: { profile: { email_address } } })` | `client.otpRequest({ emailChannel: { emailAddress } })` |
112
+ | `executeAction({ function_name: "user-upsert", input: { profile, otp_code } })` | `client.otpVerify({ otpCode, request: { emailChannel: { emailAddress } } })` |
113
+ | `executeAction({ function_name: "user-upsert", input: { profile, keys: { generic_api: { otp_channel: "sms" } } } })` | `client.otpRequest({ smsChannel: { phoneNumber } })` |
114
+ | `executeAction({ function_name: "user-upsert", input: { profile } })` (post-OTP) | `client.submitUserInput({ profile })` |
115
+
116
+ ### Worked example: full email + L1 ingest
117
+
118
+ ```typescript
119
+ import { T3nClient, UserUpsertError } from "@terminal3/t3n-sdk";
120
+
121
+ // 1) Bind the user's email via OTP.
122
+ const requested = await client.otpRequest({
123
+ emailChannel: { emailAddress: "alice@example.com" },
124
+ });
125
+ const code = await prompt(`Code sent to ${requested.contact}: `);
126
+ await client.otpVerify({
127
+ otpCode: code,
128
+ request: { emailChannel: { emailAddress: "alice@example.com" } },
129
+ });
130
+
131
+ // 2) Slim user-upsert: Level 1 user-input ingest. Rejects with
132
+ // UserUpsertError(kind: "EmailNotVerified") if step 1 was skipped.
133
+ try {
134
+ const result = await client.submitUserInput({
135
+ profile: {
136
+ first_name: "Alice",
137
+ last_name: "Smith",
138
+ country_of_residence: "US",
139
+ // ...other Level-1 fields
140
+ },
141
+ });
142
+ console.log("tx:", result.txHash);
143
+ } catch (err) {
144
+ if (err instanceof UserUpsertError && err.kind === "EmailNotVerified") {
145
+ // run otp-request + otp-verify, then retry.
146
+ }
147
+ throw err;
148
+ }
149
+ ```
150
+
151
+ For tests that "just want it to work", `runOtpThenUserInput` chains
152
+ the three calls behind a single `getOtpCode` callback.
153
+
154
+ ### Hard-error fields
155
+
156
+ Passing any of these to the wrong function returns the typed
157
+ `UserUpsertError(kind: "LegacyField")` (wire form
158
+ `legacy_field:<detail>`):
159
+
160
+ - `otp_code` to anything other than `otp-verify`.
161
+ - `keys.generic_api.otp_channel` to anything (channel is now a
162
+ top-level field).
163
+
164
+ ### Raw `executeAction` callers
165
+
166
+ If you bypass the typed wrappers, see the migration table above:
167
+ the function names (`otp-request` / `otp-verify` / `user-upsert`)
168
+ and JSON input shapes line up 1:1 with the wrappers' camelCase
169
+ fields converted to `snake_case`.
170
+
89
171
  ## Architecture
90
172
 
91
173
  The T3n SDK follows the same architectural principles as the server's `rpc.rs`: